169 lines
5.3 KiB
Rust
169 lines
5.3 KiB
Rust
//! Linux ARM64 设备后端实现
|
||
//!
|
||
//! 支持 Linux ARM64 平台的设备操作,包括显示信息、背光控制、防息屏等功能。
|
||
|
||
use crate::core::message::{DeviceCapability, DeviceCommand, DeviceResponse, PixelFormat};
|
||
use crate::plugins::device::backend::DeviceBackend;
|
||
use anyhow::Result;
|
||
use std::fs;
|
||
use std::process::{Child, Command, Stdio};
|
||
|
||
/// Linux ARM64 设备后端
|
||
///
|
||
/// 通过 sysfs 和 systemd-inhibit 实现设备控制。
|
||
pub struct LinuxArm64Backend {
|
||
/// systemd-inhibit 子进程(用于防息屏)
|
||
wake_lock_child: Option<Child>,
|
||
/// 显示宽度
|
||
display_width: u32,
|
||
/// 显示高度
|
||
display_height: u32,
|
||
/// 背光状态
|
||
backlight_enabled: bool,
|
||
}
|
||
|
||
impl LinuxArm64Backend {
|
||
/// 创建新的 Linux ARM64 后端实例
|
||
pub fn new() -> Self {
|
||
Self {
|
||
wake_lock_child: None,
|
||
display_width: 1920, // 默认分辨率
|
||
display_height: 1080,
|
||
backlight_enabled: true,
|
||
}
|
||
}
|
||
|
||
/// 读取 framebuffer 分辨率
|
||
fn read_framebuffer_resolution(&mut self) -> Result<()> {
|
||
// 尝试从 /sys/class/graphics/fb0/virtual_size 读取分辨率
|
||
if let Ok(content) = fs::read_to_string("/sys/class/graphics/fb0/virtual_size") {
|
||
let parts: Vec<&str> = content.trim().split(',').collect();
|
||
if parts.len() == 2 {
|
||
if let (Ok(width), Ok(height)) = (parts[0].parse(), parts[1].parse()) {
|
||
self.display_width = width;
|
||
self.display_height = height;
|
||
return Ok(());
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果读取失败,使用默认值(已在 new() 中设置)
|
||
Ok(())
|
||
}
|
||
|
||
/// 启动防息屏(systemd-inhibit)
|
||
fn start_sleep_inhibit(&mut self) -> Result<()> {
|
||
if self.wake_lock_child.is_some() {
|
||
return Ok(());
|
||
}
|
||
|
||
match Command::new("systemd-inhibit")
|
||
.arg("--what=idle:sleep")
|
||
.arg("--mode=block")
|
||
.arg("--who=ShowenV2")
|
||
.arg("--why=Device operation in progress")
|
||
.arg("sleep")
|
||
.arg("infinity")
|
||
.stdin(Stdio::null())
|
||
.stdout(Stdio::null())
|
||
.stderr(Stdio::null())
|
||
.spawn()
|
||
{
|
||
Ok(child) => {
|
||
self.wake_lock_child = Some(child);
|
||
Ok(())
|
||
}
|
||
Err(e) => Err(anyhow::anyhow!("Failed to start systemd-inhibit: {}", e)),
|
||
}
|
||
}
|
||
|
||
/// 停止防息屏
|
||
fn stop_sleep_inhibit(&mut self) -> Result<()> {
|
||
if let Some(mut child) = self.wake_lock_child.take() {
|
||
child.kill()?;
|
||
child.wait()?;
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 设置背光状态
|
||
fn set_backlight(&mut self, enabled: bool) -> Result<()> {
|
||
self.backlight_enabled = enabled;
|
||
|
||
// 尝试写入 /sys/class/backlight/*/brightness
|
||
// 首先查找 backlight 设备
|
||
if let Ok(entries) = fs::read_dir("/sys/class/backlight") {
|
||
for entry in entries.flatten() {
|
||
let brightness_path = entry.path().join("brightness");
|
||
let max_brightness_path = entry.path().join("max_brightness");
|
||
|
||
// 读取最大亮度
|
||
if let Ok(max_str) = fs::read_to_string(&max_brightness_path) {
|
||
if let Ok(max_brightness) = max_str.trim().parse::<u32>() {
|
||
// 设置亮度:开启时设为最大值,关闭时设为 0
|
||
let value = if enabled { max_brightness } else { 0 };
|
||
if fs::write(&brightness_path, value.to_string()).is_ok() {
|
||
return Ok(());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果没有找到 backlight 设备,返回成功(某些设备可能不支持)
|
||
Ok(())
|
||
}
|
||
}
|
||
|
||
impl DeviceBackend for LinuxArm64Backend {
|
||
fn name(&self) -> &str {
|
||
"linux-arm64"
|
||
}
|
||
|
||
fn init(&mut self, _config: &serde_json::Value) -> Result<()> {
|
||
// 读取 framebuffer 分辨率
|
||
self.read_framebuffer_resolution()?;
|
||
Ok(())
|
||
}
|
||
|
||
fn capabilities(&self) -> Vec<DeviceCapability> {
|
||
vec![
|
||
DeviceCapability::Display,
|
||
DeviceCapability::Backlight,
|
||
DeviceCapability::Framebuffer,
|
||
]
|
||
}
|
||
|
||
fn handle_command(&mut self, cmd: DeviceCommand) -> Result<DeviceResponse> {
|
||
match cmd {
|
||
DeviceCommand::GetDisplayInfo => Ok(DeviceResponse::DisplayInfo {
|
||
width: self.display_width,
|
||
height: self.display_height,
|
||
format: PixelFormat::RGB888,
|
||
}),
|
||
|
||
DeviceCommand::SetSleepInhibit(enable) => {
|
||
if enable {
|
||
self.start_sleep_inhibit()?;
|
||
} else {
|
||
self.stop_sleep_inhibit()?;
|
||
}
|
||
Ok(DeviceResponse::Ok)
|
||
}
|
||
|
||
DeviceCommand::SetBacklight(enabled) => {
|
||
self.set_backlight(enabled)?;
|
||
Ok(DeviceResponse::Ok)
|
||
}
|
||
|
||
_ => Ok(DeviceResponse::Error("Not implemented".to_string())),
|
||
}
|
||
}
|
||
|
||
fn shutdown(&mut self) -> Result<()> {
|
||
// 清理 wake_lock_child
|
||
self.stop_sleep_inhibit()?;
|
||
Ok(())
|
||
}
|
||
}
|