Files
ShowenV2/src/plugins/device/linux_arm64.rs

169 lines
5.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 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(())
}
}