Skip to content

Add command to toggle tablet mode #82

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

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions framework_lib/src/chromium_ec/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub enum EcCommands {
PwmSetFanDuty = 0x0024,
PwmSetDuty = 0x0025,
PwmGetDuty = 0x0026,
SetTabletMode = 0x0031,
GpioGet = 0x93,
I2cPassthrough = 0x9e,
ConsoleSnapshot = 0x97,
Expand Down
18 changes: 18 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,24 @@ impl EcRequest<EcResponsePwmGetDuty> for EcRequestPwmGetDuty {
}
}

pub enum TabletModeOverride {
Default = 0,
ForceTablet = 1,
ForceClamshell = 2,
}

#[repr(C, packed)]
pub struct EcRequestSetTabletMode {
/// See TabletModeOverride
pub mode: u8,
}

impl EcRequest<()> for EcRequestSetTabletMode {
fn command_id() -> EcCommands {
EcCommands::SetTabletMode
}
}

#[repr(C, packed)]
pub struct EcRequestGpioGetV0 {
pub name: [u8; 32],
Expand Down
8 changes: 7 additions & 1 deletion framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,6 @@ impl CrosEc {
}

/// Check the current brightness of the keyboard backlight
///
pub fn get_keyboard_backlight(&self) -> EcResult<u8> {
let kblight = EcRequestPwmGetDuty {
pwm_type: PwmType::KbLight as u8,
Expand All @@ -398,6 +397,13 @@ impl CrosEc {
Ok((kblight.duty / (PWM_MAX_DUTY / 100)) as u8)
}

/// Set tablet mode
pub fn set_tablet_mode(&self, mode: TabletModeOverride) {
let mode = mode as u8;
let res = EcRequestSetTabletMode { mode }.send_command(self);
print_err(res);
}

/// Overwrite RO and RW regions of EC flash
/// MEC/Legacy EC
/// | Start | End | Size | Region |
Expand Down
7 changes: 7 additions & 0 deletions framework_lib/src/commandline/clap_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use clap::Parser;
use crate::chromium_ec::CrosEcDriverType;
use crate::commandline::{
Cli, ConsoleArg, FpBrightnessArg, HardwareDeviceType, InputDeckModeArg, RebootEcArg,
TabletModeArg,
};

/// Swiss army knife for Framework laptops
Expand Down Expand Up @@ -144,6 +145,11 @@ struct ClapCli {
#[arg(long)]
kblight: Option<Option<u8>>,

/// Set tablet mode override
#[clap(value_enum)]
#[arg(long)]
tablet_mode: Option<TabletModeArg>,

/// Get EC console, choose whether recent or to follow the output
#[clap(value_enum)]
#[arg(long)]
Expand Down Expand Up @@ -263,6 +269,7 @@ pub fn parse(args: &[String]) -> Cli {
get_gpio: args.get_gpio,
fp_brightness: args.fp_brightness,
kblight: args.kblight,
tablet_mode: args.tablet_mode,
console: args.console,
reboot_ec: args.reboot_ec,
hash: args.hash.map(|x| x.into_os_string().into_string().unwrap()),
Expand Down
17 changes: 17 additions & 0 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::chromium_ec;
use crate::chromium_ec::commands::DeckStateMode;
use crate::chromium_ec::commands::FpLedBrightnessLevel;
use crate::chromium_ec::commands::RebootEcCmd;
use crate::chromium_ec::commands::TabletModeOverride;
use crate::chromium_ec::EcResponseStatus;
use crate::chromium_ec::{print_err, EcFlashType};
use crate::chromium_ec::{EcError, EcResult};
Expand All @@ -61,6 +62,14 @@ use crate::chromium_ec::{CrosEc, CrosEcDriverType, HardwareDeviceType};
#[cfg(feature = "uefi")]
use core::prelude::rust_2021::derive;

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
#[derive(Clone, Debug, PartialEq)]
pub enum TabletModeArg {
Auto,
Tablet,
Laptop,
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
#[derive(Clone, Debug, PartialEq)]
pub enum ConsoleArg {
Expand Down Expand Up @@ -152,6 +161,7 @@ pub struct Cli {
pub get_gpio: Option<String>,
pub fp_brightness: Option<Option<FpBrightnessArg>>,
pub kblight: Option<Option<u8>>,
pub tablet_mode: Option<TabletModeArg>,
pub console: Option<ConsoleArg>,
pub reboot_ec: Option<RebootEcArg>,
pub hash: Option<String>,
Expand Down Expand Up @@ -743,6 +753,13 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
} else {
println!("Unable to tell");
}
} else if let Some(tablet_arg) = &args.tablet_mode {
let mode = match tablet_arg {
TabletModeArg::Auto => TabletModeOverride::Default,
TabletModeArg::Tablet => TabletModeOverride::ForceTablet,
TabletModeArg::Laptop => TabletModeOverride::ForceClamshell,
};
ec.set_tablet_mode(mode);
} else if let Some(console_arg) = &args.console {
match console_arg {
ConsoleArg::Follow => {
Expand Down
25 changes: 24 additions & 1 deletion framework_lib/src/commandline/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use uefi::Identify;
use crate::chromium_ec::{CrosEcDriverType, HardwareDeviceType};
use crate::commandline::Cli;

use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg};
use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg, TabletModeArg};

/// Get commandline arguments from UEFI environment
pub fn get_args(boot_services: &BootServices) -> Vec<String> {
Expand Down Expand Up @@ -86,6 +86,7 @@ pub fn parse(args: &[String]) -> Cli {
get_gpio: None,
fp_brightness: None,
kblight: None,
tablet_mode: None,
console: None,
reboot_ec: None,
hash: None,
Expand Down Expand Up @@ -214,6 +215,28 @@ pub fn parse(args: &[String]) -> Cli {
Some(None)
};
found_an_option = true;
} else if arg == "--tablet-mode" {
cli.tablet_mode = if args.len() > i + 1 {
let tablet_mode_arg = &args[i + 1];
if tablet_mode_arg == "auto" {
Some(TabletModeArg::Auto)
} else if tablet_mode_arg == "tablet" {
Some(TabletModeArg::Tablet)
} else if tablet_mode_arg == "laptop" {
Some(TabletModeArg::Laptop)
} else {
println!(
"Need to provide a value for --tablet-mode: '{}'. {}",
args[i + 1],
"Must be one of: `auto`, `tablet` or `laptop`",
);
None
}
} else {
println!("Need to provide a value for --tablet-mode. One of: `auto`, `tablet` or `laptop`");
None
};
found_an_option = true;
} else if arg == "--fp-brightness" {
cli.fp_brightness = if args.len() > i + 1 {
let fp_brightness_arg = &args[i + 1];
Expand Down