Skip to content

--kblight: Fix on some early systems#285

Open
JohnAZoidberg wants to merge 2 commits intomainfrom
hx30-kblight
Open

--kblight: Fix on some early systems#285
JohnAZoidberg wants to merge 2 commits intomainfrom
hx30-kblight

Conversation

@JohnAZoidberg
Copy link
Copy Markdown
Member

@JohnAZoidberg JohnAZoidberg commented Mar 13, 2026

Tested on:

  • Framework Laptop 13 Intel 13th Gen (previously not working)
  • Framework Laptop 13 AMD Ryzen AI 300 (previously working)

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes --kblight on certain early Framework systems by detecting whether the EC supports PwmType::KbLight and falling back to an alternative PWM mapping when it does not.

Changes:

  • Added a capability probe (has_pwmtype_kblight()) based on PwmGetDuty.
  • Updated set_keyboard_backlight() to fall back to PwmType::Generic with a different index when KbLight isn’t supported.
  • Updated get_keyboard_backlight() to use the same fallback logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves keyboard backlight support on early Framework systems whose EC firmware doesn’t expose the dedicated CONFIG_PWM_KBLIGHT channel by falling back to a generic PWM channel.

Changes:

  • Add fallback in set_keyboard_backlight() to use PwmType::Generic index 1 when PwmType::KbLight returns InvalidParameter.
  • Add corresponding fallback in get_keyboard_backlight() for the same early-system behavior.
  • Refactor shared duty calculation into a local duty variable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +782 to 795
// Early systems (hx20/hx30) don't enable CONFIG_PWM_KBLIGHT in their EC firmware;
// keyboard backlight is at generic PWM channel index 1.
if let Err(EcError::Response(EcResponseStatus::InvalidParameter)) = res {
let res = EcRequestPwmSetDuty {
duty,
pwm_type: PwmType::Generic as u8,
index: 1,
}
.send_command(self);
debug_assert!(res.is_ok());
return;
}
debug_assert!(res.is_ok());
}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res is moved into the if let Err(...) = res pattern match, but then it’s used again afterwards in debug_assert!(res.is_ok()). This won’t compile because EcResult<()> isn’t Copy. Match on &res (or restructure with match res { ... }) so you can both detect InvalidParameter and still use/inspect the original result.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it definitely does compile

Comment on lines +807 to +814
let kblight = if let Err(EcError::Response(EcResponseStatus::InvalidParameter)) = res {
EcRequestPwmGetDuty {
pwm_type: PwmType::Generic as u8,
index: 1,
}
.send_command(self)?
} else {
res?
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res is moved into if let Err(...) = res, but the else branch then tries to use res?. This won’t compile due to use-after-move. Consider rewriting as a match res { Err(EcError::Response(InvalidParameter)) => { ... }, other => other? } or pattern match on &res and then handle the owned res separately.

Suggested change
let kblight = if let Err(EcError::Response(EcResponseStatus::InvalidParameter)) = res {
EcRequestPwmGetDuty {
pwm_type: PwmType::Generic as u8,
index: 1,
}
.send_command(self)?
} else {
res?
let kblight = match res {
Err(EcError::Response(EcResponseStatus::InvalidParameter)) => {
EcRequestPwmGetDuty {
pwm_type: PwmType::Generic as u8,
index: 1,
}
.send_command(self)?
}
other => other?,

Copilot uses AI. Check for mistakes.
/// * `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 as u16 * (PWM_MAX_DUTY / 100);
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duty is computed with percent as u16 * (PWM_MAX_DUTY / 100), which (a) truncates such that percent == 100 does not reach PWM_MAX_DUTY (0xFFFF), and (b) can wrap on overflow in release builds if a caller passes percent > 100 (the current debug_assert! won’t protect release builds). Compute in a wider integer type (e.g., u32) and clamp/validate percent before converting back to u16.

Suggested change
let duty = percent as u16 * (PWM_MAX_DUTY / 100);
let clamped_percent = u32::from(percent).min(100);
let duty = ((clamped_percent * u32::from(PWM_MAX_DUTY)) / 100) as u16;

Copilot uses AI. Check for mistakes.
quinchou77 and others added 2 commits March 30, 2026 00:27
I tested on Laptop 13 Intel 13th gen and kblight didn't work.

Signed-off-by: Daniel Schaefer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants