Skip to main content

kobo_core/device/
impls.rs

1//! Production (Sys) implementations of the device traits.
2//!
3//! Each `Sys*` struct wraps the corresponding free functions in the device
4//! modules. Construct once at startup and pass `&dyn Trait` to code that needs
5//! testable device access.
6
7use std::path::PathBuf;
8
9use crate::device::battery;
10use crate::device::bt::{self as bt_mod, set_bt_bus};
11use crate::device::clock;
12use crate::device::config::SocFamily;
13use crate::device::fb::Fb;
14use crate::device::power;
15use crate::device::traits::{FrontlightPaths, *};
16use crate::device::wifi;
17
18// ---------------------------------------------------------------------------
19// SysFrontlight
20// ---------------------------------------------------------------------------
21
22/// Production frontlight: reads/writes real sysfs brightness files.
23pub struct SysFrontlight {
24    brightness_path: PathBuf,
25}
26
27impl SysFrontlight {
28    pub fn new(paths: &FrontlightPaths) -> Self {
29        SysFrontlight {
30            brightness_path: paths.brightness.clone(),
31        }
32    }
33
34    pub fn from_path(path: PathBuf) -> Self {
35        SysFrontlight {
36            brightness_path: path,
37        }
38    }
39}
40
41impl Frontlight for SysFrontlight {
42    fn get(&self) -> u32 {
43        power::frontlight_get(&self.brightness_path).unwrap_or(0)
44    }
45
46    fn set(&self, brightness: u32) {
47        power::frontlight_set(&self.brightness_path, brightness);
48    }
49
50    fn restore(&self, brightness: u32) {
51        power::restore_frontlight(&self.brightness_path, brightness);
52    }
53}
54
55// ---------------------------------------------------------------------------
56// SysBattery
57// ---------------------------------------------------------------------------
58
59/// Production battery: reads `/sys/class/power_supply/*/capacity`.
60pub struct SysBattery;
61
62impl Battery for SysBattery {
63    fn pct(&self) -> i32 {
64        battery::battery_pct()
65    }
66}
67
68// ---------------------------------------------------------------------------
69// SysWifi
70// ---------------------------------------------------------------------------
71
72/// Production wifi: reads `/sys/class/net/wlan0/operstate`.
73pub struct SysWifi;
74
75impl Wifi for SysWifi {
76    fn connected(&self) -> bool {
77        wifi::wifi_status()
78    }
79
80    fn ssid(&self) -> Option<String> {
81        wifi::wifi_name()
82    }
83
84    fn toggle(&self, on: bool) {
85        wifi::wifi_toggle(on);
86    }
87}
88
89// ---------------------------------------------------------------------------
90// SysBluetooth
91// ---------------------------------------------------------------------------
92
93/// Production bluetooth: DBus calls to bluez / mtk.bluedroid.
94pub struct SysBluetooth;
95
96impl SysBluetooth {
97    /// Initialize the DBus bus name for the device's SoC family.
98    /// Call once at startup after device detection.
99    pub fn init(soc: SocFamily) -> Self {
100        set_bt_bus(soc);
101        SysBluetooth
102    }
103}
104
105impl Bluetooth for SysBluetooth {
106    fn connected(&self) -> bool {
107        bt_mod::bt_status()
108    }
109
110    fn name(&self) -> Option<String> {
111        bt_mod::bt_name()
112    }
113
114    fn toggle(&self, on: bool) {
115        bt_mod::bt_toggle(on);
116    }
117}
118
119// ---------------------------------------------------------------------------
120// SysSystemControl
121// ---------------------------------------------------------------------------
122
123/// Production system control: kernel suspend via `/sys/power/state`,
124/// wall-clock via `date` command.
125pub struct SysSystemControl;
126
127impl SystemControl for SysSystemControl {
128    fn suspend(&self, state: &str) {
129        power::kernel_suspend(state);
130    }
131
132    fn clock(&self) -> String {
133        clock::current_clock()
134    }
135}
136
137// ---------------------------------------------------------------------------
138// SysFramebuffer
139// ---------------------------------------------------------------------------
140
141/// Production framebuffer: wraps [`Fb`] (mmap'd `/dev/fb0` + MXCFB refresh).
142pub struct SysFramebuffer<'a> {
143    fb: &'a Fb,
144}
145
146impl<'a> SysFramebuffer<'a> {
147    pub fn new(fb: &'a Fb) -> Self {
148        SysFramebuffer { fb }
149    }
150}
151
152impl<'a> Framebuffer for SysFramebuffer<'a> {
153    fn resolution(&self) -> (usize, usize) {
154        (self.fb.xres, self.fb.yres)
155    }
156
157    fn present(
158        &self,
159        buf: &[u8],
160        w: usize,
161        h: usize,
162        full: bool,
163        top: usize,
164        rh: usize,
165        waveform: u32,
166    ) {
167        self.fb.present(buf, w, h, full, top, rh, waveform);
168    }
169}
170
171/// Resolve frontlight sysfs paths from a [`crate::device::config::FrontlightConfig`].
172pub fn resolve_frontlight_paths(
173    fl_cfg: &crate::device::config::FrontlightConfig,
174) -> FrontlightPaths {
175    FrontlightPaths {
176        brightness: power::known_brightness_path(fl_cfg),
177        mixer: power::frontlight_path(fl_cfg),
178    }
179}