feature: add support for screenpad brightness

This commit is contained in:
Luke Jones
2025-04-06 00:57:04 +13:00
parent 257471a36c
commit 7f5b3ef376
13 changed files with 505 additions and 26 deletions

View File

@@ -0,0 +1,75 @@
use std::path::PathBuf;
use log::{info, warn};
use crate::error::{PlatformError, Result};
use crate::{attr_num, to_device};
/// The "backlight" device provides access to screen brightness control
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
pub struct Backlight {
path: PathBuf,
device_type: BacklightType,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone)]
pub enum BacklightType {
Primary,
Screenpad,
}
impl Backlight {
attr_num!("brightness", path, i32);
attr_num!("max_brightness", path, i32);
attr_num!("bl_power", path, i32);
pub fn new(device_type: BacklightType) -> Result<Self> {
let mut enumerator = udev::Enumerator::new().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("enumerator failed".into(), err)
})?;
enumerator.match_subsystem("backlight").map_err(|err| {
warn!("{}", err);
PlatformError::Udev("match_subsystem failed".into(), err)
})?;
for device in enumerator.scan_devices().map_err(|err| {
warn!("{}", err);
PlatformError::Udev("scan_devices failed".into(), err)
})? {
info!("Backlight: Checking {:?}", device.syspath());
match device_type {
BacklightType::Primary => {
if device.sysname().to_string_lossy() == "intel_backlight" {
info!("Found primary backlight at {:?}", device.sysname());
return Ok(Self {
path: device.syspath().to_path_buf(),
device_type,
});
}
}
BacklightType::Screenpad => {
let name = device.sysname().to_string_lossy();
if name == "asus_screenpad" || name == "asus_screenpad_backlight" {
info!("Found screenpad backlight at {:?}", device.sysname());
return Ok(Self {
path: device.syspath().to_path_buf(),
device_type,
});
}
}
}
}
Err(PlatformError::MissingFunction(format!(
"Backlight {:?} not found",
device_type
)))
}
pub fn device_type(&self) -> &BacklightType {
&self.device_type
}
}

View File

@@ -3,7 +3,7 @@ use std::path::PathBuf;
use log::{info, warn};
use crate::error::{PlatformError, Result};
use crate::{attr_u8, has_attr, set_attr_u8_array, to_device};
use crate::{attr_num, has_attr, set_attr_u8_array, to_device};
/// The sysfs control for backlight levels. This is only for the 3-step
/// backlight setting, and for TUF laptops. It is not a hard requirement
@@ -14,7 +14,7 @@ pub struct KeyboardBacklight {
}
impl KeyboardBacklight {
attr_u8!("brightness", path);
attr_num!("brightness", path, u8);
has_attr!("kbd_rgb_mode" path);

View File

@@ -2,6 +2,7 @@
//! on ROG, Strix, and TUF laptops.
pub mod asus_armoury;
pub mod backlight;
pub mod cpu;
pub mod error;
pub mod hid_raw;
@@ -55,18 +56,29 @@ pub fn write_attr_bool(device: &mut Device, attr: &str, value: bool) -> Result<(
})
}
pub fn read_attr_u8(device: &Device, attr_name: &str) -> Result<u8> {
pub fn read_attr_num<T>(device: &Device, attr_name: &str) -> Result<T>
where
T: std::str::FromStr,
<T as std::str::FromStr>::Err: std::fmt::Debug,
{
if let Some(value) = device.attribute_value(attr_name) {
let tmp = value.to_string_lossy();
return tmp.parse::<u8>().map_err(|_e| PlatformError::ParseNum);
return tmp.parse::<T>().map_err(|_e| PlatformError::ParseNum);
}
Err(PlatformError::AttrNotFound(attr_name.to_owned()))
}
pub fn write_attr_u8(device: &mut Device, attr: &str, value: u8) -> Result<()> {
device
.set_attribute_value(attr, value.to_string())
.map_err(|e| PlatformError::IoPath(attr.into(), e))
pub fn write_attr_num<T>(device: &mut Device, attr_name: &str, value: T) -> Result<()>
where
T: std::fmt::Display,
{
if device
.set_attribute_value(attr_name, format!("{value}"))
.is_err()
{
return Err(PlatformError::AttrNotFound(attr_name.to_owned()));
}
Ok(())
}
pub fn read_attr_u8_array(device: &Device, attr_name: &str) -> Result<Vec<u8>> {

View File

@@ -74,36 +74,41 @@ macro_rules! attr_bool {
}
#[macro_export]
macro_rules! get_attr_u8 {
($(#[$attr:meta])* $attr_name:literal $item:ident) => {
macro_rules! get_attr_num {
($(#[$attr:meta])* $attr_name:literal $item:ident $type:ty) => {
concat_idents::concat_idents!(fn_name = get_, $attr_name {
$(#[$attr])*
pub fn fn_name(&self) -> Result<u8> {
$crate::read_attr_u8(&to_device(&self.$item)?, $attr_name)
pub fn fn_name(&self) -> Result<$type> {
$crate::read_attr_num::<$type>(&to_device(&self.$item)?, $attr_name)
}
});
};
($(#[$attr:meta])* $attr_name:literal $item:ident) => {
$crate::get_attr_num!($(#[$attr])* $attr_name $item $type);
};
}
/// Most attributes expect `u8` as a char, so `1` should be written as `b'1'`.
#[macro_export]
macro_rules! set_attr_u8 {
($(#[$attr:meta])* $attr_name:literal $item:ident) => {
macro_rules! set_attr_num {
($(#[$attr:meta])* $attr_name:literal $item:ident $type:ty) => {
concat_idents::concat_idents!(fn_name = set_, $attr_name {
$(#[$attr])*
pub fn fn_name(&self, value: u8) -> Result<()> {
$crate::write_attr_u8(&mut to_device(&self.$item)?, $attr_name, value)
pub fn fn_name(&self, value: $type) -> Result<()> {
$crate::write_attr_num(&mut to_device(&self.$item)?, $attr_name, value as $type)
}
});
};
($(#[$attr:meta])* $attr_name:literal $item:ident) => {
$crate::set_attr_num!($(#[$attr])* $attr_name $item $type);
};
}
#[macro_export]
macro_rules! attr_u8 {
($(#[$attr:meta])* $attr_name:literal, $item:ident) => {
macro_rules! attr_num {
($(#[$attr:meta])* $attr_name:literal, $item:ident, $type:ty) => {
$crate::has_attr!($(#[$attr])* $attr_name $item);
$crate::get_attr_u8!($(#[$attr])* $attr_name $item);
$crate::set_attr_u8!($(#[$attr])* $attr_name $item);
$crate::get_attr_num!($(#[$attr])* $attr_name $item $type);
$crate::set_attr_num!($(#[$attr])* $attr_name $item $type);
$crate::watch_attr!($(#[$attr])* $attr_name $item);
};
}

View File

@@ -3,7 +3,7 @@ use std::path::PathBuf;
use log::{info, warn};
use crate::error::{PlatformError, Result};
use crate::{attr_u8, to_device};
use crate::{attr_num, to_device};
/// The "platform" device provides access to things like:
/// - `dgpu_disable`
@@ -20,9 +20,9 @@ pub struct AsusPower {
}
impl AsusPower {
attr_u8!("charge_control_end_threshold", battery);
attr_num!("charge_control_end_threshold", battery, u8);
attr_u8!("online", mains);
attr_num!("online", mains, u8);
/// When checking for battery this will look in order:
/// - if attr `manufacturer` contains `asus`