diff --git a/src/app/main/smfi.c b/src/app/main/smfi.c index 5c61b75f2..c9b485ad1 100644 --- a/src/app/main/smfi.c +++ b/src/app/main/smfi.c @@ -161,6 +161,24 @@ static enum Result cmd_fan_set_pwm(void) { return RES_ERR; } +static enum Result cmd_fan_get_rpm(void) { + switch (smfi_cmd[SMFI_CMD_DATA]) { + case 1: + smfi_cmd[SMFI_CMD_DATA + 1] = (uint8_t)fan1_rpm; + smfi_cmd[SMFI_CMD_DATA + 2] = (uint8_t)(fan1_rpm >> 8); + return RES_OK; + #ifdef FAN2_PWM + case 2: + smfi_cmd[SMFI_CMD_DATA + 1] = (uint8_t)fan2_rpm; + smfi_cmd[SMFI_CMD_DATA + 2] = (uint8_t)(fan2_rpm >> 8); + return RES_OK; +#endif + } + + // Failed if fan not found + return RES_ERR; +} + static enum Result cmd_fan_get_mode(void) { smfi_cmd[SMFI_CMD_DATA] = fan_get_mode(); return RES_OK; @@ -443,6 +461,9 @@ void smfi_event(void) { break; #endif // CONFIG_SECURITY + case CMD_FAN_GET_RPM: + smfi_cmd[SMFI_CMD_RES] = cmd_fan_get_rpm(); + break; case CMD_FAN_GET_MODE: smfi_cmd[SMFI_CMD_RES] = cmd_fan_get_mode(); break; diff --git a/src/common/include/common/command.h b/src/common/include/common/command.h index ecec85bd0..726861bd0 100644 --- a/src/common/include/common/command.h +++ b/src/common/include/common/command.h @@ -50,10 +50,16 @@ enum Command { CMD_SECURITY_GET = 20, // Set security state CMD_SECURITY_SET = 21, + // Get fan RPM + CMD_FAN_GET_RPM = 22, // Get fan control mode - CMD_FAN_GET_MODE = 22, + CMD_FAN_GET_MODE = 23, // Set fan control mode - CMD_FAN_SET_MODE = 23, + CMD_FAN_SET_MODE = 24, + // Get case revision + CMD_CASE_REV_GET = 25, + // Set case revision + CMD_CASE_REV_SET = 26, }; enum Result { diff --git a/tools/system76_ectool/src/ec.rs b/tools/system76_ectool/src/ec.rs index cc04f9cf5..d6b7f32ad 100644 --- a/tools/system76_ectool/src/ec.rs +++ b/tools/system76_ectool/src/ec.rs @@ -33,8 +33,11 @@ enum Cmd { SetNoInput = 19, SecurityGet = 20, SecuritySet = 21, - FanGetMode = 22, - FanSetMode = 23, + FanGetRpm = 22, + FanGetMode = 23, + FanSetMode = 24, + CaseRevGet = 25, + CaseRevSet = 26, } const CMD_SPI_FLAG_READ: u8 = 1 << 0; @@ -318,6 +321,14 @@ impl Ec { unsafe { self.command(Cmd::SecuritySet, &mut data) } } + /// Get fan tachometer. + pub unsafe fn fan_get_rpm(&mut self, index: u8) -> Result { + let mut data = [index, 0, 0]; + data[0] = index; + unsafe { self.command(Cmd::FanGetRpm, &mut data)? }; + Ok((data[1] as u16) | ((data[2] as u16) << 8)) + } + /// Get fan control mode. pub unsafe fn fan_get_mode(&mut self) -> Result { let mut data = [0]; @@ -331,6 +342,19 @@ impl Ec { unsafe { self.command(Cmd::FanSetMode, &mut data) } } + /// Get case revision + pub unsafe fn case_rev_get(&mut self) -> Result { + let mut data = [0; 4]; + unsafe { self.command(Cmd::CaseRevGet, &mut data)? }; + Ok(u32::from_le_bytes(data)) + } + + /// Set case revision + pub unsafe fn case_rev_set(&mut self, rev: u32) -> Result<(), Error> { + let mut data = rev.to_le_bytes(); + unsafe { self.command(Cmd::CaseRevSet, &mut data) } + } + pub fn into_dyn(self) -> Ec> where A: 'static, diff --git a/tools/system76_ectool/src/main.rs b/tools/system76_ectool/src/main.rs index 05e754460..96a13a22a 100644 --- a/tools/system76_ectool/src/main.rs +++ b/tools/system76_ectool/src/main.rs @@ -274,6 +274,13 @@ unsafe fn fan_set_pwm(ec: &mut Ec>, index: u8, duty: u8) -> Resu unsafe { ec.fan_set_pwm(index, duty) } } +unsafe fn fan_get_rpm(ec: &mut Ec>, index: u8) -> Result<(), Error> { + let rpm = unsafe { ec.fan_get_rpm(index)? }; + println!("{}", rpm); + + Ok(()) +} + unsafe fn fan_get_mode(ec: &mut Ec>) -> Result<(), Error> { let mode = unsafe { ec.fan_get_mode()? }; println!("{}", mode); @@ -285,6 +292,17 @@ unsafe fn fan_set_mode(ec: &mut Ec>, mode: ectool::FanMode) -> R unsafe { ec.fan_set_mode(mode) } } +unsafe fn case_rev_get(ec: &mut Ec>) -> Result<(), Error> { + let rev = unsafe { ec.case_rev_get()? }; + println!("{}", rev); + + Ok(()) +} + +unsafe fn case_rev_set(ec: &mut Ec>, rev: u32) -> Result<(), Error> { + unsafe { ec.case_rev_set(rev) } +} + unsafe fn keymap_get( ec: &mut Ec>, layer: u8, @@ -333,13 +351,19 @@ fn parse_color(s: &str) -> Result<(u8, u8, u8), String> { #[derive(Parser)] #[clap(rename_all = "snake_case")] enum SubCommand { + CaseRev { + rev: Option, + }, Console, + FanMode { + mode: Option, + }, FanPwm { index: u8, duty: Option, }, - FanMode { - mode: Option, + FanRpm { + index: u8, }, Flash { path: String, @@ -426,7 +450,13 @@ fn main() { // System76 launch_2 (0x3384, 0x0006, 1) | // System76 launch_heavy_1 - (0x3384, 0x0007, 1) => { + (0x3384, 0x0007, 1) | + // System76 launch_3 + (0x3384, 0x0009, 1) | + // System76 launch_heavy_3 + (0x3384, 0x000A, 1) | + // System76 thelio_io_2 + (0x3384, 0x000B, 1) => { let device = info.open_device(&api)?; let access = AccessHid::new(device, 10, 100)?; return Ok(Ec::new(access)?.into_dyn()); @@ -448,6 +478,24 @@ fn main() { }; match args.subcommand { + SubCommand::CaseRev { + rev, + } => match rev { + Some(rev) => match unsafe { case_rev_set(&mut ec, rev) } { + Ok(()) => (), + Err(err) => { + eprintln!("failed to set case revision {}: {:X?}", rev, err); + process::exit(1); + } + }, + None => match unsafe { case_rev_get(&mut ec) } { + Ok(()) => (), + Err(err) => { + eprintln!("failed to get case revision: {:X?}", err); + process::exit(1); + } + }, + }, SubCommand::Console => match unsafe { console(&mut ec) } { Ok(()) => (), Err(err) => { @@ -492,6 +540,15 @@ fn main() { } }, }, + SubCommand::FanRpm { + index, + } => match unsafe { fan_get_rpm(&mut ec, index) } { + Ok(()) => (), + Err(err) => { + eprintln!("failed to get fan rpm {}: {:X?}", index, err); + process::exit(1); + } + }, SubCommand::Flash { path, } => match unsafe { flash(&mut ec, &path, SpiTarget::Main) } {