Skip to content
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
8 changes: 4 additions & 4 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,13 @@ ALS: 76 Lux
```

### Accelerometer (Framework 12)

```
> sudo framework_tool --sensors
ALS: 0 Lux
Accelerometers:
Lid Angle: 122 Deg
Sensor 1: X=+0.00G Y=+0.84G, Z=+0.52G
Sensor 2: X=-0.03G Y=+0.00G, Z=+1.01G
Lid Angle: 118 Deg
Lid Sensor: X=+0.00G Y=+0.86G, Z=+0.53G
Base Sensor: X=-0.03G Y=-0.07G, Z=+1.02G
```

## Set custom fan duty/RPM
Expand Down
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 {
PwmSetKeyboardBacklight = 0x0023,
PwmSetFanDuty = 0x0024,
PwmSetDuty = 0x0025,
MotionSense = 0x002B,
PwmGetDuty = 0x0026,
SetTabletMode = 0x0031,
AutoFanCtrl = 0x0052,
Expand Down
128 changes: 128 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,134 @@ impl EcRequest<EcResponsePwmGetDuty> for EcRequestPwmGetDuty {
}
}

#[repr(u8)]
pub enum MotionSenseCmd {
Dump = 0,
Info = 1,
}

#[repr(C, packed)]
pub struct EcRequestMotionSenseDump {
/// MotionSenseCmd::Dump
pub cmd: u8,
/// Maximal number of sensor the host is expecting.
/// 0 means the host is only interested in the number
/// of sensors controlled by the EC.
pub max_sensor_count: u8,
}

#[repr(C, packed)]
pub struct EcResponseMotionSenseDump {
/// Flags representing the motion sensor module
pub module_flags: u8,

/// Number of sensors managed directly by the EC
pub sensor_count: u8,

/// Sensor data is truncated if response_max is too small
/// for holding all the data.
pub sensor: [u8; 0],
}

impl EcRequest<EcResponseMotionSenseDump> for EcRequestMotionSenseDump {
fn command_id() -> EcCommands {
EcCommands::MotionSense
}
fn command_version() -> u8 {
1
}
}

#[derive(Debug, FromPrimitive, PartialEq)]
pub enum MotionSenseType {
Accel = 0,
Gyro = 1,
Mag = 2,
Prox = 3,
Light = 4,
Activity = 5,
Baro = 6,
Sync = 7,
LightRgb = 8,
}

#[derive(Debug, FromPrimitive)]
pub enum MotionSenseLocation {
Base = 0,
Lid = 1,
Camera = 2,
}

#[derive(Debug, FromPrimitive)]
pub enum MotionSenseChip {
Kxcj9 = 0,
Lsm6ds0 = 1,
Bmi160 = 2,
Si1141 = 3,
Si1142 = 4,
Si1143 = 5,
Kx022 = 6,
L3gd20h = 7,
Bma255 = 8,
Bmp280 = 9,
Opt3001 = 10,
Bh1730 = 11,
Gpio = 12,
Lis2dh = 13,
Lsm6dsm = 14,
Lis2de = 15,
Lis2mdl = 16,
Lsm6ds3 = 17,
Lsm6dso = 18,
Lng2dm = 19,
Tcs3400 = 20,
Lis2dw12 = 21,
Lis2dwl = 22,
Lis2ds = 23,
Bmi260 = 24,
Icm426xx = 25,
Icm42607 = 26,
Bma422 = 27,
Bmi323 = 28,
Bmi220 = 29,
Cm32183 = 30,
Veml3328 = 31,
}

#[repr(C, packed)]
pub struct EcRequestMotionSenseInfo {
/// MotionSenseCmd::Info
pub cmd: u8,
/// Sensor index
pub sensor_num: u8,
}

#[repr(C)]
pub struct EcResponseMotionSenseInfo {
/// See enum MotionSenseInfo
pub sensor_type: u8,
/// See enum MotionSenseLocation
pub location: u8,
/// See enum MotionSenseChip
pub chip: u8,
}

#[derive(Debug)]
pub struct MotionSenseInfo {
pub sensor_type: MotionSenseType,
pub location: MotionSenseLocation,
pub chip: MotionSenseChip,
}

impl EcRequest<EcResponseMotionSenseInfo> for EcRequestMotionSenseInfo {
fn command_id() -> EcCommands {
EcCommands::MotionSense
}
fn command_version() -> u8 {
1
}
}

pub enum TabletModeOverride {
Default = 0,
ForceTablet = 1,
Expand Down
37 changes: 37 additions & 0 deletions framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,43 @@ impl CrosEc {
))
}

pub fn motionsense_sensor_count(&self) -> EcResult<u8> {
EcRequestMotionSenseDump {
cmd: MotionSenseCmd::Dump as u8,
max_sensor_count: 0,
}
.send_command(self)
.map(|res| res.sensor_count)
}

pub fn motionsense_sensor_info(&self) -> EcResult<Vec<MotionSenseInfo>> {
let count = self.motionsense_sensor_count()?;

let mut sensors = vec![];
for sensor_num in 0..count {
let info = EcRequestMotionSenseInfo {
cmd: MotionSenseCmd::Info as u8,
sensor_num,
}
.send_command(self)?;
sensors.push(MotionSenseInfo {
sensor_type: FromPrimitive::from_u8(info.sensor_type).unwrap(),
location: FromPrimitive::from_u8(info.location).unwrap(),
chip: FromPrimitive::from_u8(info.chip).unwrap(),
});
}
Ok(sensors)
}

pub fn motionsense_sensor_list(&self) -> EcResult<u8> {
EcRequestMotionSenseDump {
cmd: MotionSenseCmd::Dump as u8,
max_sensor_count: 0,
}
.send_command(self)
.map(|res| res.sensor_count)
}

/// Get current status of Framework Laptop's microphone and camera privacy switches
/// [true = device enabled/connected, false = device disabled]
pub fn get_privacy_info(&self) -> EcResult<(bool, bool)> {
Expand Down
71 changes: 57 additions & 14 deletions framework_lib/src/power.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Get information about system power (battery, AC, PD ports)

use alloc::format;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
Expand All @@ -10,11 +11,11 @@ use log::Level;

use crate::ccgx::{AppVersion, Application, BaseVersion, ControllerVersion, MainPdVersions};
use crate::chromium_ec::command::EcRequestRaw;
use crate::chromium_ec::commands::{EcRequestReadPdVersion, EcRequestUsbPdPowerInfo};
use crate::chromium_ec::{print_err_ref, CrosEc, CrosEcDriver, EcResult};
use crate::chromium_ec::commands::*;
use crate::chromium_ec::*;
use crate::smbios;
use crate::smbios::get_platform;
use crate::util::Platform;
use crate::util::{Platform, PlatformFamily};

/// Maximum length of strings in memmap
const EC_MEMMAP_TEXT_MAX: u16 = 8;
Expand Down Expand Up @@ -245,9 +246,15 @@ pub fn print_memmap_version_info(ec: &CrosEc) {
}

/// Not supported on TGL EC
pub fn get_als_reading(ec: &CrosEc) -> Option<u32> {
pub fn get_als_reading(ec: &CrosEc, index: usize) -> Option<u32> {
let als = ec.read_memory(EC_MEMMAP_ALS, 0x04)?;
Some(u32::from_le_bytes([als[0], als[1], als[2], als[3]]))
let offset = index + 4 * index;
Some(u32::from_le_bytes([
als[offset],
als[1 + offset],
als[2 + offset],
als[3 + offset],
]))
}

pub fn get_accel_data(ec: &CrosEc) -> (AccelData, AccelData, LidAngle) {
Expand All @@ -274,8 +281,40 @@ pub fn get_accel_data(ec: &CrosEc) -> (AccelData, AccelData, LidAngle) {
}

pub fn print_sensors(ec: &CrosEc) {
let als_int = get_als_reading(ec).unwrap();
println!("ALS: {:>4} Lux", als_int);
let mut has_als = false;
let mut accel_locations = vec![];

match ec.motionsense_sensor_info() {
Ok(sensors) => {
info!("Sensors: {}", sensors.len());
for sensor in sensors {
info!(" Type: {:?}", sensor.sensor_type);
info!(" Location: {:?}", sensor.location);
info!(" Chip: {:?}", sensor.chip);
if sensor.sensor_type == MotionSenseType::Light {
has_als = true;
}
if sensor.sensor_type == MotionSenseType::Accel {
accel_locations.push(sensor.location);
}
}
}
Err(EcError::Response(EcResponseStatus::InvalidCommand)) => {
debug!("Motionsense commands not supported")
}
err => _ = print_err(err),
}

// If we can't detect it based on motionsense
let als_family = matches!(
smbios::get_family(),
Some(PlatformFamily::Framework13) | Some(PlatformFamily::Framework16)
);

if has_als || als_family {
let als_int = get_als_reading(ec, 0).unwrap();
println!("ALS: {:>4} Lux", als_int);
}

// bit 4 = busy
// bit 7 = present
Expand All @@ -294,18 +333,22 @@ pub fn print_sensors(ec: &CrosEc) {
debug!(" Status Bit: {} 0x{:X}", acc_status, acc_status);
debug!(" Present: {}", present);
debug!(" Busy: {}", (acc_status & 0x8) > 0);
print!(" Lid Angle: ");
print!(" Lid Angle: ");
if lid_angle == LID_ANGLE_UNRELIABLE {
println!("Unreliable");
} else {
println!("{} Deg", lid_angle);
}
println!(" Sensor 1: {}", AccelData::from(accel_1));
println!(" Sensor 2: {}", AccelData::from(accel_2));
// Accelerometers
// Lid Angle: 26 Deg
// Sensor 1: 00.00 X 00.00 Y 00.00 Z
// Sensor 2: 00.00 X 00.00 Y 00.00 Z
println!(
" {:<12} {}",
format!("{:?} Sensor:", accel_locations[0]),
AccelData::from(accel_1)
);
println!(
" {:<12} {}",
format!("{:?} Sensor:", accel_locations[1]),
AccelData::from(accel_2)
);
}
}

Expand Down
6 changes: 5 additions & 1 deletion framework_lib/src/smbios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::prelude::v1::*;
use std::io::ErrorKind;

use crate::util::Config;
pub use crate::util::Platform;
pub use crate::util::{Platform, PlatformFamily};
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use smbioslib::*;
Expand Down Expand Up @@ -271,6 +271,10 @@ pub fn get_baseboard_version() -> Option<ConfigDigit0> {
})
}

pub fn get_family() -> Option<PlatformFamily> {
get_platform().and_then(Platform::which_family)
}

pub fn get_platform() -> Option<Platform> {
#[cfg(feature = "uefi")]
let mut cached_platform = CACHED_PLATFORM.lock();
Expand Down
Loading