-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #85 from liketechnik/feat/sysfs-charging-profiles
feat(tuxedo_sysfs): implement charging profiles
- Loading branch information
Showing
7 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
use std::io; | ||
|
||
use crate::sysfs_util::{ | ||
r_file, read_int_list, read_path_to_int_list, read_path_to_string, read_to_string, write_int, | ||
write_string, | ||
}; | ||
|
||
use super::BatteryChargeControl; | ||
|
||
const SYSFS_POWER_SUPPLY_PATH: &str = "/sys/class/power_supply"; | ||
const TYPE: &str = "/type"; | ||
const CHARGE_TYPE: &str = "/charge_type"; | ||
const START_THRESHOLD: &str = "/charge_control_start_threshold"; | ||
const END_THRESHOLD: &str = "/charge_control_end_threshold"; | ||
const AVAILABLE_START_THRESHOLDS: &str = "/charge_control_start_available_thresholds"; | ||
const AVAILABLE_END_THRESHOLDS: &str = "/charge_control_end_available_thresholds"; | ||
|
||
impl BatteryChargeControl { | ||
pub async fn new( | ||
name: String, | ||
available_start_thresholds: Option<Vec<u32>>, | ||
available_end_thresholds: Option<Vec<u32>>, | ||
start_threshold_file: tokio_uring::fs::File, | ||
end_threshold_file: tokio_uring::fs::File, | ||
charge_type_file: tokio_uring::fs::File, | ||
) -> Result<Self, io::Error> { | ||
Ok(Self { | ||
name, | ||
available_start_thresholds, | ||
available_end_thresholds, | ||
start_threshold_file, | ||
end_threshold_file, | ||
charge_type_file, | ||
}) | ||
} | ||
|
||
pub async fn new_first_battery() -> Result<Option<Self>, io::Error> { | ||
let mut dirs = tokio::fs::read_dir(SYSFS_POWER_SUPPLY_PATH).await?; | ||
while let Some(dir) = dirs.next_entry().await? { | ||
let path = dir.path(); | ||
|
||
let file_name = path | ||
.file_name() | ||
.expect("the sysfs path must have a last segment"); | ||
|
||
let type_path = path.join(TYPE); | ||
if let Ok(typ) = read_path_to_string(type_path).await { | ||
// not a battery, uninteresting | ||
if typ.trim() != "Battery" { | ||
continue; | ||
} | ||
} else { | ||
tracing::warn!("Type file can't be read: {:?}", file_name); | ||
continue; | ||
} | ||
|
||
let start_threshold_file = | ||
if let Ok(start_threshold_file) = r_file(path.join(START_THRESHOLD)).await { | ||
start_threshold_file | ||
} else { | ||
// thresholds not supported | ||
continue; | ||
}; | ||
let end_threshold_file = | ||
if let Ok(end_threshold_file) = r_file(path.join(END_THRESHOLD)).await { | ||
end_threshold_file | ||
} else { | ||
// thresholds not supported | ||
continue; | ||
}; | ||
let charge_type_file = | ||
if let Ok(charge_type_file) = r_file(path.join(CHARGE_TYPE)).await { | ||
charge_type_file | ||
} else { | ||
// thresholds not supported | ||
continue; | ||
}; | ||
|
||
let available_start_thresholds_file = path.join(AVAILABLE_START_THRESHOLDS); | ||
let available_start_thresholds = read_path_to_int_list(available_start_thresholds_file) | ||
.await | ||
.ok(); | ||
|
||
let available_end_thresholds_file = path.join(AVAILABLE_END_THRESHOLDS); | ||
let available_end_thresholds = read_path_to_int_list(available_end_thresholds_file) | ||
.await | ||
.ok(); | ||
|
||
let name = file_name.to_string_lossy().into_owned(); | ||
|
||
// TODO: if there is more than 1 battery in the system, | ||
// there is no guarantee which one is returned | ||
return Ok(Some( | ||
BatteryChargeControl::new( | ||
name, | ||
available_start_thresholds, | ||
available_end_thresholds, | ||
start_threshold_file, | ||
end_threshold_file, | ||
charge_type_file, | ||
) | ||
.await?, | ||
)); | ||
} | ||
|
||
Ok(None) | ||
} | ||
|
||
pub async fn get_start_threshold(&mut self) -> Result<u32, io::Error> { | ||
Ok(*read_int_list(&mut self.start_threshold_file) | ||
.await? | ||
.first() | ||
.expect("start threshold file returns a value on read")) | ||
} | ||
|
||
pub async fn get_end_threshold(&mut self) -> Result<u32, io::Error> { | ||
Ok(*read_int_list(&mut self.end_threshold_file) | ||
.await? | ||
.first() | ||
.expect("end threshold file returns a value on read")) | ||
} | ||
|
||
pub async fn get_charge_type(&mut self) -> Result<String, io::Error> { | ||
Ok(read_to_string(&mut self.charge_type_file) | ||
.await? | ||
.trim() | ||
.to_owned()) | ||
} | ||
|
||
/// <https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power> | ||
/// (section charge_type) | ||
pub async fn set_charge_type(&mut self, charge_type: String) -> Result<(), io::Error> { | ||
write_string(&mut self.charge_type_file, charge_type).await | ||
} | ||
|
||
/// generally: 0-100, | ||
/// but may be further restricted to [`Self::available_start_thresholds`] | ||
pub async fn set_start_threshold(&mut self, threshold: u32) -> Result<(), io::Error> { | ||
write_int(&mut self.start_threshold_file, threshold).await | ||
} | ||
|
||
/// generally: 0-100, | ||
/// but may be further restricted to [`Self::available_end_thresholds`] | ||
pub async fn set_end_threshold(&mut self, threshold: u32) -> Result<(), io::Error> { | ||
write_int(&mut self.end_threshold_file, threshold).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use std::io; | ||
|
||
use crate::sysfs_util::{r_file, read_to_string, read_to_string_list, rw_file, write_string}; | ||
|
||
use super::ChargingPriority; | ||
|
||
const CHARGING_PRIORITY_PATH: &str = | ||
"/sys/devices/platform/tuxedo_keyboard/charging_profile/charging_prio"; | ||
const CHARGING_PRIORITIES_AVAILABLE_PATH: &str = | ||
"/sys/devices/platform/tuxedo_keyboard/charging_profile/charging_prios_available"; | ||
|
||
impl ChargingPriority { | ||
pub async fn new() -> Result<Option<Self>, io::Error> { | ||
let mut available_charging_priorities_file = | ||
match r_file(CHARGING_PRIORITIES_AVAILABLE_PATH).await { | ||
Ok(f) => f, | ||
Err(_) => return Ok(None), | ||
}; | ||
let priorities = read_to_string_list(&mut available_charging_priorities_file).await?; | ||
|
||
let priority_file = rw_file(CHARGING_PRIORITY_PATH).await?; | ||
|
||
Ok(Some(ChargingPriority { | ||
available_charging_priorities: priorities, | ||
charging_priority_file: priority_file, | ||
})) | ||
} | ||
|
||
pub async fn get_charging_priority(&mut self) -> Result<String, io::Error> { | ||
Ok(read_to_string(&mut self.charging_priority_file) | ||
.await? | ||
.trim() | ||
.to_owned()) | ||
} | ||
|
||
/// charge_battery, performance | ||
/// src/ng-app/app/charging-settings/charging-settings.component.ts | ||
/// in TCC | ||
/// / src/uniwill_keyboard.h in tuxedo-keyboard | ||
pub async fn set_charging_priority(&mut self, priority: String) -> Result<(), io::Error> { | ||
write_string(&mut self.charging_priority_file, priority).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use std::io; | ||
|
||
use crate::sysfs_util::{r_file, read_to_string, read_to_string_list, rw_file, write_string}; | ||
|
||
use super::ChargingProfile; | ||
|
||
const CHARGING_PROFILE_PATH: &str = | ||
"/sys/devices/platform/tuxedo_keyboard/charging_profile/charging_profile"; | ||
const CHARGING_PROFILES_AVAILABLE_PATH: &str = | ||
"/sys/devices/platform/tuxedo_keyboard/charging_profile/charging_profiles_available"; | ||
|
||
impl ChargingProfile { | ||
pub async fn new() -> Result<Option<Self>, io::Error> { | ||
let mut available_charging_profiles_file = | ||
match r_file(CHARGING_PROFILES_AVAILABLE_PATH).await { | ||
Ok(f) => f, | ||
Err(_) => return Ok(None), | ||
}; | ||
let available_charging_profiles = | ||
read_to_string_list(&mut available_charging_profiles_file).await?; | ||
let charging_profile_file = rw_file(CHARGING_PROFILE_PATH).await?; | ||
|
||
Ok(Some(ChargingProfile { | ||
available_charging_profiles, | ||
charging_profile_file, | ||
})) | ||
} | ||
|
||
pub async fn get_charging_profile(&mut self) -> Result<String, io::Error> { | ||
Ok(read_to_string(&mut self.charging_profile_file) | ||
.await? | ||
.trim() | ||
.to_owned()) | ||
} | ||
|
||
/// high_capacity, balanced, stationary according to | ||
/// src/ng-app/app/charging-settings/charging-settings.component.ts | ||
/// in TCC | ||
/// / src/uniwill_keyboard.h in tuxedo-keyboard | ||
pub async fn set_charging_profile(&mut self, profile: String) -> Result<(), io::Error> { | ||
write_string(&mut self.charging_profile_file, profile).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
mod charge_control; | ||
mod charging_priority; | ||
mod charging_profile; | ||
|
||
/// A type that manages all sysfs files related to | ||
/// charging profile options provided by the tuxedo_keyboard driver. | ||
/// | ||
/// The charging profile imposes a firmware-enforced limit on the maximum charge of the | ||
/// battery. | ||
pub struct ChargingProfile { | ||
pub available_charging_profiles: Vec<String>, | ||
charging_profile_file: tokio_uring::fs::File, | ||
} | ||
|
||
/// A type that manages all sysfs files related to | ||
/// charging priority options provided by the tuxedo_keyboard driver. | ||
/// | ||
/// The charging priority determines whether charging speed or | ||
/// performance is prioritized when charging over USB-C. | ||
pub struct ChargingPriority { | ||
pub available_charging_priorities: Vec<String>, | ||
charging_priority_file: tokio_uring::fs::File, | ||
} | ||
|
||
/// A type that manages all sysfs files related to charging start/end thresholds. | ||
pub struct BatteryChargeControl { | ||
pub name: String, | ||
pub available_start_thresholds: Option<Vec<u32>>, | ||
pub available_end_thresholds: Option<Vec<u32>>, | ||
/// Percentage value between 0-100, | ||
/// [`Self::available_start_thresholds`] lists further restrictions on accepted values. | ||
start_threshold_file: tokio_uring::fs::File, | ||
/// Percentage value between 0-100, | ||
/// [`Self::available_end_thresholds`] lists further restrictions on accepted values. | ||
end_threshold_file: tokio_uring::fs::File, | ||
/// Must be 'Custom' to allow for custom thresholds. | ||
/// | ||
/// Possible values listed at <https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power> (section: /sys/class/power_supply/<supply_name>/charge_type) | ||
charge_type_file: tokio_uring::fs::File, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod charging; | ||
pub mod led; | ||
pub(crate) mod sysfs_util; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters