mirror of
https://gitlab.steamos.cloud/holo/steamos-manager.git
synced 2025-07-07 15:10:29 -04:00
cec: Add module and interface for accessing/controlling state
This commit is contained in:
parent
bf521a7bbb
commit
1dcdfb2b23
5 changed files with 147 additions and 4 deletions
|
@ -258,10 +258,21 @@
|
||||||
com.steampowered.SteamOSManager1.UserManager
|
com.steampowered.SteamOSManager1.UserManager
|
||||||
@short_description: Interface to control various aspects of SteamOS running as a user.
|
@short_description: Interface to control various aspects of SteamOS running as a user.
|
||||||
|
|
||||||
Version available: 8
|
Version available: 8
|
||||||
-->
|
-->
|
||||||
<interface name="com.steampowered.SteamOSManager1.UserManager">
|
<interface name="com.steampowered.SteamOSManager1.UserManager">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
HdmiCecState:
|
||||||
|
|
||||||
|
The current state of HDMI-CEC features on the system
|
||||||
|
|
||||||
|
Valid states: 0 = Disabled, 1 = Control Only, 2 = Control And Wake
|
||||||
|
|
||||||
|
Version available: 8
|
||||||
|
-->
|
||||||
|
<property name="HdmiCecState" type="u" access="readwrite"/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Version:
|
Version:
|
||||||
|
|
||||||
|
@ -270,6 +281,8 @@
|
||||||
The manager may not support the latest version of the API.
|
The manager may not support the latest version of the API.
|
||||||
Each method/property has an associated version number that
|
Each method/property has an associated version number that
|
||||||
denotes in which interface version it first became available.
|
denotes in which interface version it first became available.
|
||||||
|
|
||||||
|
Version available: 8
|
||||||
-->
|
-->
|
||||||
<property name="Version" type="u" access="read"/>
|
<property name="Version" type="u" access="read"/>
|
||||||
|
|
||||||
|
|
102
src/cec.rs
Normal file
102
src/cec.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2023 Collabora Ltd.
|
||||||
|
* Copyright © 2024 Valve Software
|
||||||
|
* Copyright © 2024 Igalia S.L.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use std::fmt;
|
||||||
|
use zbus::Connection;
|
||||||
|
|
||||||
|
use crate::systemd::{daemon_reload, EnableState, SystemdUnit};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
|
pub enum HdmiCecState {
|
||||||
|
Disabled = 0,
|
||||||
|
ControlOnly = 1,
|
||||||
|
ControlAndWake = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for HdmiCecState {
|
||||||
|
type Error = &'static str;
|
||||||
|
fn try_from(v: u32) -> Result<Self, Self::Error> {
|
||||||
|
match v {
|
||||||
|
x if x == HdmiCecState::Disabled as u32 => Ok(HdmiCecState::Disabled),
|
||||||
|
x if x == HdmiCecState::ControlOnly as u32 => Ok(HdmiCecState::ControlOnly),
|
||||||
|
x if x == HdmiCecState::ControlAndWake as u32 => Ok(HdmiCecState::ControlAndWake),
|
||||||
|
_ => Err("No enum match for value {v}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for HdmiCecState {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
HdmiCecState::Disabled => write!(f, "Disabled"),
|
||||||
|
HdmiCecState::ControlOnly => write!(f, "ControlOnly"),
|
||||||
|
HdmiCecState::ControlAndWake => write!(f, "ControlAndWake"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HdmiCecControl<'dbus> {
|
||||||
|
plasma_rc_unit: SystemdUnit<'dbus>,
|
||||||
|
wakehook_unit: SystemdUnit<'dbus>,
|
||||||
|
connection: Connection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'dbus> HdmiCecControl<'dbus> {
|
||||||
|
pub async fn new(connection: &Connection) -> Result<HdmiCecControl<'dbus>> {
|
||||||
|
Ok(HdmiCecControl {
|
||||||
|
plasma_rc_unit: SystemdUnit::new(
|
||||||
|
connection.clone(),
|
||||||
|
"plasma-remotecontrollers.service",
|
||||||
|
)
|
||||||
|
.await?,
|
||||||
|
wakehook_unit: SystemdUnit::new(connection.clone(), "wakehook.service").await?,
|
||||||
|
connection: connection.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_enabled_state(&self) -> Result<HdmiCecState> {
|
||||||
|
Ok(match self.plasma_rc_unit.enabled().await? {
|
||||||
|
EnableState::Enabled | EnableState::Static => {
|
||||||
|
match self.wakehook_unit.enabled().await? {
|
||||||
|
EnableState::Enabled | EnableState::Static => HdmiCecState::ControlAndWake,
|
||||||
|
_ => HdmiCecState::ControlOnly,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => HdmiCecState::Disabled,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_enabled_state(&self, state: HdmiCecState) -> Result<()> {
|
||||||
|
match state {
|
||||||
|
HdmiCecState::Disabled => {
|
||||||
|
self.plasma_rc_unit.mask().await?;
|
||||||
|
self.plasma_rc_unit.stop().await?;
|
||||||
|
self.wakehook_unit.mask().await?;
|
||||||
|
self.wakehook_unit.stop().await?;
|
||||||
|
daemon_reload(&self.connection).await?;
|
||||||
|
}
|
||||||
|
HdmiCecState::ControlOnly => {
|
||||||
|
self.wakehook_unit.mask().await?;
|
||||||
|
self.wakehook_unit.stop().await?;
|
||||||
|
self.plasma_rc_unit.unmask().await?;
|
||||||
|
daemon_reload(&self.connection).await?;
|
||||||
|
self.plasma_rc_unit.start().await?;
|
||||||
|
}
|
||||||
|
HdmiCecState::ControlAndWake => {
|
||||||
|
self.plasma_rc_unit.unmask().await?;
|
||||||
|
self.wakehook_unit.unmask().await?;
|
||||||
|
daemon_reload(&self.connection).await?;
|
||||||
|
self.plasma_rc_unit.start().await?;
|
||||||
|
self.wakehook_unit.start().await?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ use tokio::signal::unix::{signal, SignalKind};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
|
mod cec;
|
||||||
mod daemon;
|
mod daemon;
|
||||||
mod ds_inhibit;
|
mod ds_inhibit;
|
||||||
mod hardware;
|
mod hardware;
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub async fn daemon() -> Result<()> {
|
||||||
bail!(e);
|
bail!(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let session = match create_connection().await {
|
let _session = match create_connection().await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _guard = tracing::subscriber::set_default(subscriber);
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||||||
|
|
|
@ -7,22 +7,49 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use tracing::error;
|
||||||
use zbus::{interface, Connection};
|
use zbus::{interface, Connection};
|
||||||
|
|
||||||
use crate::API_VERSION;
|
use crate::{to_zbus_error, to_zbus_fdo_error, API_VERSION};
|
||||||
|
use crate::cec::{HdmiCecControl, HdmiCecState};
|
||||||
|
|
||||||
pub struct SteamOSManagerUser {
|
pub struct SteamOSManagerUser {
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
|
hdmi_cec: HdmiCecControl<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SteamOSManagerUser {
|
impl SteamOSManagerUser {
|
||||||
pub async fn new(connection: Connection) -> Result<Self> {
|
pub async fn new(connection: Connection) -> Result<Self> {
|
||||||
Ok(SteamOSManagerUser { connection })
|
Ok(SteamOSManagerUser {
|
||||||
|
hdmi_cec: HdmiCecControl::new(&connection).await?,
|
||||||
|
connection,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interface(name = "com.steampowered.SteamOSManager1.UserManager")]
|
#[interface(name = "com.steampowered.SteamOSManager1.UserManager")]
|
||||||
impl SteamOSManagerUser {
|
impl SteamOSManagerUser {
|
||||||
|
#[zbus(property(emits_changed_signal = "false"))]
|
||||||
|
async fn hdmi_cec_state(&self) -> zbus::fdo::Result<u32> {
|
||||||
|
match self.hdmi_cec.get_enabled_state().await {
|
||||||
|
Ok(state) => Ok(state as u32),
|
||||||
|
Err(e) => Err(to_zbus_fdo_error(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
async fn set_hdmi_cec_state(&self, state: u32) -> zbus::Result<()> {
|
||||||
|
let state = match HdmiCecState::try_from(state) {
|
||||||
|
Ok(state) => state,
|
||||||
|
Err(err) => return Err(zbus::fdo::Error::InvalidArgs(err.to_string()).into()),
|
||||||
|
};
|
||||||
|
self.hdmi_cec
|
||||||
|
.set_enabled_state(state)
|
||||||
|
.await
|
||||||
|
.inspect_err(|message| error!("Error setting CEC state: {message}"))
|
||||||
|
.map_err(to_zbus_error)
|
||||||
|
}
|
||||||
|
|
||||||
#[zbus(property(emits_changed_signal = "const"))]
|
#[zbus(property(emits_changed_signal = "const"))]
|
||||||
async fn version(&self) -> u32 {
|
async fn version(&self) -> u32 {
|
||||||
API_VERSION
|
API_VERSION
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue