Skip to content

Commit 0ae8af2

Browse files
committed
backlight: make the display backlight controllable via the broker framework
This allows changing the display brightness via the API and provides the ground work to allow dimming of the backlight in the screensaver. Signed-off-by: Leonard Göhrs <l.goehrs@pengutronix.de>
1 parent d398d60 commit 0ae8af2

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed

openapi.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,30 @@ paths:
4141
schema:
4242
$ref: '#/components/schemas/Alerts'
4343

44+
/v1/tac/display/backlight/brightness:
45+
get:
46+
summary: Get the current backlight brightness (between 0.0, and 1.0)
47+
tags: [User Interface]
48+
responses:
49+
'200':
50+
content:
51+
application/json:
52+
schema:
53+
type: number
54+
put:
55+
summary: Set the current backlight brightness (between 0.0 and 1.0)
56+
tags: [User Interface]
57+
requestBody:
58+
content:
59+
application/json:
60+
schema:
61+
type: number
62+
responses:
63+
'204':
64+
description: The display brightness was set sucessfully
65+
'400':
66+
description: The value could not be parsed as a number
67+
4468
/v1/tac/display/buttons:
4569
put:
4670
summary: Simulate a button press/release on the device

src/backlight.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// This file is part of tacd, the LXA TAC system daemon
2+
// Copyright (C) 2023 Pengutronix e.K.
3+
//
4+
// This program is free software; you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation; either version 2 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License along
15+
// with this program; if not, write to the Free Software Foundation, Inc.,
16+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
18+
use anyhow::Result;
19+
use async_std::prelude::*;
20+
use async_std::sync::Arc;
21+
use async_std::task::spawn;
22+
use log::warn;
23+
24+
mod demo_mode;
25+
26+
#[cfg(feature = "demo_mode")]
27+
use demo_mode::{Backlight as SysBacklight, Brightness, SysClass};
28+
29+
#[cfg(not(feature = "demo_mode"))]
30+
use sysfs_class::{Backlight as SysBacklight, Brightness, SysClass};
31+
32+
use crate::broker::{BrokerBuilder, Topic};
33+
34+
pub struct Backlight {
35+
pub brightness: Arc<Topic<f32>>,
36+
}
37+
38+
impl Backlight {
39+
pub fn new(bb: &mut BrokerBuilder) -> Result<Self> {
40+
let brightness = bb.topic_rw("/v1/tac/display/backlight/brightness", Some(1.0));
41+
42+
let (mut rx, _) = brightness.clone().subscribe_unbounded();
43+
44+
let backlight = SysBacklight::new("backlight")?;
45+
let max_brightness = backlight.max_brightness()?;
46+
47+
spawn(async move {
48+
while let Some(fraction) = rx.next().await {
49+
let brightness = (max_brightness as f32) * fraction;
50+
let mut brightness = brightness.clamp(0.0, max_brightness as f32) as u64;
51+
52+
// A brightness of 0 turns the backlight off completely.
53+
// If the user selects something low but not zero they likely
54+
// want a dim glow, not completely off.
55+
if fraction > 0.01 && brightness == 0 {
56+
brightness = 1;
57+
}
58+
59+
if let Err(e) = backlight.set_brightness(brightness) {
60+
warn!("Failed to set LED pattern: {}", e);
61+
}
62+
}
63+
});
64+
65+
Ok(Self { brightness })
66+
}
67+
}

src/backlight/demo_mode.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// This file is part of tacd, the LXA TAC system daemon
2+
// Copyright (C) 2023 Pengutronix e.K.
3+
//
4+
// This program is free software; you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation; either version 2 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License along
15+
// with this program; if not, write to the Free Software Foundation, Inc.,
16+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
18+
use std::io::{Error, ErrorKind, Result};
19+
use std::path::{Path, PathBuf};
20+
use std::str::{from_utf8, FromStr};
21+
22+
use sysfs_class::{set_trait_method, trait_method};
23+
24+
pub trait SysClass: Sized {
25+
fn class() -> &'static str;
26+
unsafe fn from_path_unchecked(path: PathBuf) -> Self;
27+
fn path(&self) -> &Path;
28+
29+
fn new(id: &str) -> Result<Self> {
30+
let inst = unsafe { Self::from_path_unchecked(id.into()) };
31+
Ok(inst)
32+
}
33+
34+
fn read_file<P: AsRef<Path>>(&self, name: P) -> Result<String> {
35+
let path = self.path().join(name);
36+
let path = path.to_str().unwrap();
37+
38+
if path == "backlight/max_brightness" {
39+
Ok("8".to_string())
40+
} else {
41+
Err(Error::new(ErrorKind::NotFound, format!("{path} not found")))
42+
}
43+
}
44+
45+
fn parse_file<F: FromStr, P: AsRef<Path>>(&self, name: P) -> Result<F> {
46+
self.read_file(name)?
47+
.parse()
48+
.map_err(|_| Error::new(ErrorKind::InvalidData, "too bad"))
49+
}
50+
51+
fn write_file<P: AsRef<Path>, S: AsRef<[u8]>>(&self, name: P, data: S) -> Result<()> {
52+
let path = self.path().join(name);
53+
let path = path.to_str().unwrap();
54+
let data = from_utf8(data.as_ref()).unwrap();
55+
56+
log::info!("Backlight: Write {} to {}", data, path);
57+
58+
Ok(())
59+
}
60+
}
61+
62+
pub trait Brightness {
63+
fn brightness(&self) -> Result<u64>;
64+
fn max_brightness(&self) -> Result<u64>;
65+
fn set_brightness(&self, val: u64) -> Result<()>;
66+
}
67+
68+
pub struct Backlight {
69+
path: PathBuf,
70+
}
71+
72+
impl SysClass for Backlight {
73+
fn class() -> &'static str {
74+
"backlight"
75+
}
76+
77+
unsafe fn from_path_unchecked(path: PathBuf) -> Self {
78+
Self { path }
79+
}
80+
81+
fn path(&self) -> &Path {
82+
&self.path
83+
}
84+
}
85+
86+
impl Brightness for Backlight {
87+
trait_method!(brightness parse_file u64);
88+
trait_method!(max_brightness parse_file u64);
89+
set_trait_method!("brightness", set_brightness u64);
90+
}

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use futures::{select, FutureExt};
1919

2020
mod adc;
21+
mod backlight;
2122
mod broker;
2223
mod dbus;
2324
mod digital_io;
@@ -36,6 +37,7 @@ mod usb_hub;
3637
mod watchdog;
3738

3839
use adc::Adc;
40+
use backlight::Backlight;
3941
use broker::BrokerBuilder;
4042
use dbus::DbusSession;
4143
use digital_io::DigitalIo;
@@ -64,6 +66,7 @@ async fn main() -> Result<(), std::io::Error> {
6466
let mut bb = BrokerBuilder::new();
6567

6668
// Expose hardware on the TAC via the broker framework.
69+
let backlight = Backlight::new(&mut bb).unwrap();
6770
let led = Led::new(&mut bb);
6871
let adc = Adc::new(&mut bb).await.unwrap();
6972
let dut_pwr = DutPwrThread::new(
@@ -117,6 +120,7 @@ async fn main() -> Result<(), std::io::Error> {
117120
let ui = {
118121
let resources = UiResources {
119122
adc,
123+
backlight,
120124
dig_io,
121125
dut_pwr,
122126
iobus,

src/ui.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use screens::{splash, ActivatableScreen, AlertScreen, NormalScreen, Screen};
3939

4040
pub struct UiResources {
4141
pub adc: crate::adc::Adc,
42+
pub backlight: crate::backlight::Backlight,
4243
pub dig_io: crate::digital_io::DigitalIo,
4344
pub dut_pwr: crate::dut_power::DutPwrThread,
4445
pub iobus: crate::iobus::IoBus,

0 commit comments

Comments
 (0)