add evfbo (evdev + fbdev + stdout) backend
During a normal boot in the postmarketOS initramfs, the TTY is not easily accessible. The on-screen keyboard is expected to send the password to stdout instead of to a uinput device. Add the evfbo backend to support full-disk encryption.
This commit is contained in:
parent
7b38edb656
commit
c92b571c16
4 changed files with 185 additions and 0 deletions
|
|
@ -37,6 +37,10 @@ bindgen = "0.71"
|
|||
name = "ufkbd-evfb"
|
||||
path = "src/ufkbd_evfb.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "ufkbd-evfbo"
|
||||
path = "src/ufkbd_evfbo.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "ufkbd-gnome"
|
||||
path = "src/ufkbd_gnome.rs"
|
||||
|
|
|
|||
8
src/stdio/mod.rs
Normal file
8
src/stdio/mod.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2025, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
mod output;
|
||||
|
||||
pub use self::output::Output;
|
||||
92
src/stdio/output.rs
Normal file
92
src/stdio/output.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2025, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
use crate::core::Keyboard;
|
||||
use crate::core::Layout;
|
||||
use std::iter::FromIterator;
|
||||
use xkeysym::Keysym;
|
||||
|
||||
pub struct Output {
|
||||
back: String,
|
||||
front: String,
|
||||
complete: bool,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
pub fn new() -> Self
|
||||
{
|
||||
Self {
|
||||
back: String::new(),
|
||||
front: String::new(),
|
||||
complete: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn complete(&self) -> bool
|
||||
{
|
||||
self.complete
|
||||
}
|
||||
}
|
||||
|
||||
impl Keyboard for Output {
|
||||
fn key_supported(&self, sym: Keysym) -> bool
|
||||
{
|
||||
match sym {
|
||||
Keysym::Return => true,
|
||||
Keysym::BackSpace => true,
|
||||
Keysym::Delete => true,
|
||||
Keysym::Left => true,
|
||||
Keysym::Right => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn press(&mut self, sym: Keysym)
|
||||
{
|
||||
match sym {
|
||||
Keysym::Return => {
|
||||
let front = self.front.chars().rev();
|
||||
let front = String::from_iter(front);
|
||||
|
||||
println!("{}{}", self.back, front);
|
||||
|
||||
self.complete = true;
|
||||
},
|
||||
Keysym::BackSpace => {
|
||||
self.back.pop();
|
||||
},
|
||||
Keysym::Delete => {
|
||||
self.front.pop();
|
||||
},
|
||||
Keysym::Left => {
|
||||
if let Some(c) = self.back.pop() {
|
||||
self.front.push(c);
|
||||
}
|
||||
},
|
||||
Keysym::Right => {
|
||||
if let Some(c) = self.front.pop() {
|
||||
self.back.push(c);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn release(&mut self, _: Keysym)
|
||||
{
|
||||
}
|
||||
|
||||
fn text(&mut self, text: &str)
|
||||
{
|
||||
for c in text.chars() {
|
||||
self.back.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
fn change_layout(&mut self, _: &Layout)
|
||||
{
|
||||
}
|
||||
}
|
||||
81
src/ufkbd_evfbo.rs
Normal file
81
src/ufkbd_evfbo.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Copyright (c) 2025, Richard Acayan. All rights reserved.
|
||||
*/
|
||||
|
||||
mod core;
|
||||
mod evdev;
|
||||
mod fbdev;
|
||||
mod linux;
|
||||
mod stdio;
|
||||
|
||||
use crate::core::Button;
|
||||
use crate::core::Configuration;
|
||||
use crate::core::Display;
|
||||
use crate::core::Graphics;
|
||||
use crate::core::Layout;
|
||||
use crate::evdev::Touchscreen;
|
||||
use crate::fbdev::Framebuffer;
|
||||
use crate::stdio::Output;
|
||||
use polling::Event;
|
||||
use polling::Events;
|
||||
use polling::Poller;
|
||||
use signal_hook::consts::signal;
|
||||
use signal_hook::iterator::Signals;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main()
|
||||
{
|
||||
let cfg = Configuration::load().unwrap();
|
||||
let disp = Framebuffer::new(&cfg).unwrap();
|
||||
|
||||
let gfx = Graphics::new(disp, &cfg);
|
||||
let gfx = Mutex::new(gfx);
|
||||
let gfx = Arc::new(gfx);
|
||||
|
||||
let kbd = Output::new();
|
||||
let layout = Layout::load(&cfg).unwrap();
|
||||
let mut btn = Button::new(&cfg, layout, kbd, gfx.clone());
|
||||
btn.set_text_supported(true);
|
||||
|
||||
{
|
||||
let mut gfx = gfx.lock().unwrap();
|
||||
let (width, height) = gfx.display().size();
|
||||
gfx.resize(btn.layout(), btn.mod_state(), width, height);
|
||||
}
|
||||
|
||||
let mut touchscreen = Touchscreen::new(btn, &cfg).unwrap();
|
||||
|
||||
let mut events = Events::new();
|
||||
let poller = Poller::new().unwrap();
|
||||
let ts_evt = Event::readable(0);
|
||||
|
||||
let mut sigs = Signals::new([
|
||||
signal::SIGHUP,
|
||||
signal::SIGINT,
|
||||
signal::SIGPIPE,
|
||||
signal::SIGTERM,
|
||||
]).unwrap();
|
||||
|
||||
unsafe {
|
||||
poller.add(&touchscreen, ts_evt).unwrap();
|
||||
}
|
||||
|
||||
while sigs.pending().next().is_none() && !touchscreen.button().keyboard().complete() {
|
||||
let timer = touchscreen.button().next_time().map(|t| t - Instant::now());
|
||||
|
||||
events.clear();
|
||||
poller.modify(&touchscreen, ts_evt).unwrap();
|
||||
poller.wait(&mut events, timer).unwrap();
|
||||
|
||||
if !events.is_empty() {
|
||||
touchscreen.handle_events();
|
||||
}
|
||||
|
||||
touchscreen.dispatch_timers();
|
||||
}
|
||||
|
||||
poller.delete(&touchscreen).unwrap();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue