Skip to content

Commit d30f728

Browse files
Merge pull request #143 from FrameworkComputer/simple-motionsense
--sensors: Get information about sensors
2 parents c2e8bed + 36cd61e commit d30f728

File tree

6 files changed

+232
-19
lines changed

6 files changed

+232
-19
lines changed

EXAMPLES.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,13 @@ ALS: 76 Lux
173173
```
174174

175175
### Accelerometer (Framework 12)
176+
176177
```
177178
> sudo framework_tool --sensors
178-
ALS: 0 Lux
179179
Accelerometers:
180-
Lid Angle: 122 Deg
181-
Sensor 1: X=+0.00G Y=+0.84G, Z=+0.52G
182-
Sensor 2: X=-0.03G Y=+0.00G, Z=+1.01G
180+
Lid Angle: 118 Deg
181+
Lid Sensor: X=+0.00G Y=+0.86G, Z=+0.53G
182+
Base Sensor: X=-0.03G Y=-0.07G, Z=+1.02G
183183
```
184184

185185
## Set custom fan duty/RPM

framework_lib/src/chromium_ec/command.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub enum EcCommands {
3333
PwmSetKeyboardBacklight = 0x0023,
3434
PwmSetFanDuty = 0x0024,
3535
PwmSetDuty = 0x0025,
36+
MotionSense = 0x002B,
3637
PwmGetDuty = 0x0026,
3738
SetTabletMode = 0x0031,
3839
AutoFanCtrl = 0x0052,

framework_lib/src/chromium_ec/commands.rs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,134 @@ impl EcRequest<EcResponsePwmGetDuty> for EcRequestPwmGetDuty {
282282
}
283283
}
284284

285+
#[repr(u8)]
286+
pub enum MotionSenseCmd {
287+
Dump = 0,
288+
Info = 1,
289+
}
290+
291+
#[repr(C, packed)]
292+
pub struct EcRequestMotionSenseDump {
293+
/// MotionSenseCmd::Dump
294+
pub cmd: u8,
295+
/// Maximal number of sensor the host is expecting.
296+
/// 0 means the host is only interested in the number
297+
/// of sensors controlled by the EC.
298+
pub max_sensor_count: u8,
299+
}
300+
301+
#[repr(C, packed)]
302+
pub struct EcResponseMotionSenseDump {
303+
/// Flags representing the motion sensor module
304+
pub module_flags: u8,
305+
306+
/// Number of sensors managed directly by the EC
307+
pub sensor_count: u8,
308+
309+
/// Sensor data is truncated if response_max is too small
310+
/// for holding all the data.
311+
pub sensor: [u8; 0],
312+
}
313+
314+
impl EcRequest<EcResponseMotionSenseDump> for EcRequestMotionSenseDump {
315+
fn command_id() -> EcCommands {
316+
EcCommands::MotionSense
317+
}
318+
fn command_version() -> u8 {
319+
1
320+
}
321+
}
322+
323+
#[derive(Debug, FromPrimitive, PartialEq)]
324+
pub enum MotionSenseType {
325+
Accel = 0,
326+
Gyro = 1,
327+
Mag = 2,
328+
Prox = 3,
329+
Light = 4,
330+
Activity = 5,
331+
Baro = 6,
332+
Sync = 7,
333+
LightRgb = 8,
334+
}
335+
336+
#[derive(Debug, FromPrimitive)]
337+
pub enum MotionSenseLocation {
338+
Base = 0,
339+
Lid = 1,
340+
Camera = 2,
341+
}
342+
343+
#[derive(Debug, FromPrimitive)]
344+
pub enum MotionSenseChip {
345+
Kxcj9 = 0,
346+
Lsm6ds0 = 1,
347+
Bmi160 = 2,
348+
Si1141 = 3,
349+
Si1142 = 4,
350+
Si1143 = 5,
351+
Kx022 = 6,
352+
L3gd20h = 7,
353+
Bma255 = 8,
354+
Bmp280 = 9,
355+
Opt3001 = 10,
356+
Bh1730 = 11,
357+
Gpio = 12,
358+
Lis2dh = 13,
359+
Lsm6dsm = 14,
360+
Lis2de = 15,
361+
Lis2mdl = 16,
362+
Lsm6ds3 = 17,
363+
Lsm6dso = 18,
364+
Lng2dm = 19,
365+
Tcs3400 = 20,
366+
Lis2dw12 = 21,
367+
Lis2dwl = 22,
368+
Lis2ds = 23,
369+
Bmi260 = 24,
370+
Icm426xx = 25,
371+
Icm42607 = 26,
372+
Bma422 = 27,
373+
Bmi323 = 28,
374+
Bmi220 = 29,
375+
Cm32183 = 30,
376+
Veml3328 = 31,
377+
}
378+
379+
#[repr(C, packed)]
380+
pub struct EcRequestMotionSenseInfo {
381+
/// MotionSenseCmd::Info
382+
pub cmd: u8,
383+
/// Sensor index
384+
pub sensor_num: u8,
385+
}
386+
387+
#[repr(C)]
388+
pub struct EcResponseMotionSenseInfo {
389+
/// See enum MotionSenseInfo
390+
pub sensor_type: u8,
391+
/// See enum MotionSenseLocation
392+
pub location: u8,
393+
/// See enum MotionSenseChip
394+
pub chip: u8,
395+
}
396+
397+
#[derive(Debug)]
398+
pub struct MotionSenseInfo {
399+
pub sensor_type: MotionSenseType,
400+
pub location: MotionSenseLocation,
401+
pub chip: MotionSenseChip,
402+
}
403+
404+
impl EcRequest<EcResponseMotionSenseInfo> for EcRequestMotionSenseInfo {
405+
fn command_id() -> EcCommands {
406+
EcCommands::MotionSense
407+
}
408+
fn command_version() -> u8 {
409+
1
410+
}
411+
}
412+
285413
pub enum TabletModeOverride {
286414
Default = 0,
287415
ForceTablet = 1,

framework_lib/src/chromium_ec/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,43 @@ impl CrosEc {
353353
))
354354
}
355355

356+
pub fn motionsense_sensor_count(&self) -> EcResult<u8> {
357+
EcRequestMotionSenseDump {
358+
cmd: MotionSenseCmd::Dump as u8,
359+
max_sensor_count: 0,
360+
}
361+
.send_command(self)
362+
.map(|res| res.sensor_count)
363+
}
364+
365+
pub fn motionsense_sensor_info(&self) -> EcResult<Vec<MotionSenseInfo>> {
366+
let count = self.motionsense_sensor_count()?;
367+
368+
let mut sensors = vec![];
369+
for sensor_num in 0..count {
370+
let info = EcRequestMotionSenseInfo {
371+
cmd: MotionSenseCmd::Info as u8,
372+
sensor_num,
373+
}
374+
.send_command(self)?;
375+
sensors.push(MotionSenseInfo {
376+
sensor_type: FromPrimitive::from_u8(info.sensor_type).unwrap(),
377+
location: FromPrimitive::from_u8(info.location).unwrap(),
378+
chip: FromPrimitive::from_u8(info.chip).unwrap(),
379+
});
380+
}
381+
Ok(sensors)
382+
}
383+
384+
pub fn motionsense_sensor_list(&self) -> EcResult<u8> {
385+
EcRequestMotionSenseDump {
386+
cmd: MotionSenseCmd::Dump as u8,
387+
max_sensor_count: 0,
388+
}
389+
.send_command(self)
390+
.map(|res| res.sensor_count)
391+
}
392+
356393
/// Get current status of Framework Laptop's microphone and camera privacy switches
357394
/// [true = device enabled/connected, false = device disabled]
358395
pub fn get_privacy_info(&self) -> EcResult<(bool, bool)> {

framework_lib/src/power.rs

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Get information about system power (battery, AC, PD ports)
22
3+
use alloc::format;
34
use alloc::string::String;
45
use alloc::vec;
56
use alloc::vec::Vec;
@@ -10,11 +11,11 @@ use log::Level;
1011

1112
use crate::ccgx::{AppVersion, Application, BaseVersion, ControllerVersion, MainPdVersions};
1213
use crate::chromium_ec::command::EcRequestRaw;
13-
use crate::chromium_ec::commands::{EcRequestReadPdVersion, EcRequestUsbPdPowerInfo};
14-
use crate::chromium_ec::{print_err_ref, CrosEc, CrosEcDriver, EcResult};
14+
use crate::chromium_ec::commands::*;
15+
use crate::chromium_ec::*;
1516
use crate::smbios;
1617
use crate::smbios::get_platform;
17-
use crate::util::Platform;
18+
use crate::util::{Platform, PlatformFamily};
1819

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

247248
/// Not supported on TGL EC
248-
pub fn get_als_reading(ec: &CrosEc) -> Option<u32> {
249+
pub fn get_als_reading(ec: &CrosEc, index: usize) -> Option<u32> {
249250
let als = ec.read_memory(EC_MEMMAP_ALS, 0x04)?;
250-
Some(u32::from_le_bytes([als[0], als[1], als[2], als[3]]))
251+
let offset = index + 4 * index;
252+
Some(u32::from_le_bytes([
253+
als[offset],
254+
als[1 + offset],
255+
als[2 + offset],
256+
als[3 + offset],
257+
]))
251258
}
252259

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

276283
pub fn print_sensors(ec: &CrosEc) {
277-
let als_int = get_als_reading(ec).unwrap();
278-
println!("ALS: {:>4} Lux", als_int);
284+
let mut has_als = false;
285+
let mut accel_locations = vec![];
286+
287+
match ec.motionsense_sensor_info() {
288+
Ok(sensors) => {
289+
info!("Sensors: {}", sensors.len());
290+
for sensor in sensors {
291+
info!(" Type: {:?}", sensor.sensor_type);
292+
info!(" Location: {:?}", sensor.location);
293+
info!(" Chip: {:?}", sensor.chip);
294+
if sensor.sensor_type == MotionSenseType::Light {
295+
has_als = true;
296+
}
297+
if sensor.sensor_type == MotionSenseType::Accel {
298+
accel_locations.push(sensor.location);
299+
}
300+
}
301+
}
302+
Err(EcError::Response(EcResponseStatus::InvalidCommand)) => {
303+
debug!("Motionsense commands not supported")
304+
}
305+
err => _ = print_err(err),
306+
}
307+
308+
// If we can't detect it based on motionsense
309+
let als_family = matches!(
310+
smbios::get_family(),
311+
Some(PlatformFamily::Framework13) | Some(PlatformFamily::Framework16)
312+
);
313+
314+
if has_als || als_family {
315+
let als_int = get_als_reading(ec, 0).unwrap();
316+
println!("ALS: {:>4} Lux", als_int);
317+
}
279318

280319
// bit 4 = busy
281320
// bit 7 = present
@@ -294,18 +333,22 @@ pub fn print_sensors(ec: &CrosEc) {
294333
debug!(" Status Bit: {} 0x{:X}", acc_status, acc_status);
295334
debug!(" Present: {}", present);
296335
debug!(" Busy: {}", (acc_status & 0x8) > 0);
297-
print!(" Lid Angle: ");
336+
print!(" Lid Angle: ");
298337
if lid_angle == LID_ANGLE_UNRELIABLE {
299338
println!("Unreliable");
300339
} else {
301340
println!("{} Deg", lid_angle);
302341
}
303-
println!(" Sensor 1: {}", AccelData::from(accel_1));
304-
println!(" Sensor 2: {}", AccelData::from(accel_2));
305-
// Accelerometers
306-
// Lid Angle: 26 Deg
307-
// Sensor 1: 00.00 X 00.00 Y 00.00 Z
308-
// Sensor 2: 00.00 X 00.00 Y 00.00 Z
342+
println!(
343+
" {:<12} {}",
344+
format!("{:?} Sensor:", accel_locations[0]),
345+
AccelData::from(accel_1)
346+
);
347+
println!(
348+
" {:<12} {}",
349+
format!("{:?} Sensor:", accel_locations[1]),
350+
AccelData::from(accel_2)
351+
);
309352
}
310353
}
311354

framework_lib/src/smbios.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::prelude::v1::*;
66
use std::io::ErrorKind;
77

88
use crate::util::Config;
9-
pub use crate::util::Platform;
9+
pub use crate::util::{Platform, PlatformFamily};
1010
use num_derive::FromPrimitive;
1111
use num_traits::FromPrimitive;
1212
use smbioslib::*;
@@ -271,6 +271,10 @@ pub fn get_baseboard_version() -> Option<ConfigDigit0> {
271271
})
272272
}
273273

274+
pub fn get_family() -> Option<PlatformFamily> {
275+
get_platform().and_then(Platform::which_family)
276+
}
277+
274278
pub fn get_platform() -> Option<Platform> {
275279
#[cfg(feature = "uefi")]
276280
let mut cached_platform = CACHED_PLATFORM.lock();

0 commit comments

Comments
 (0)