acid/firmware/acid-firmware/src/ui/mod.rs
Jakub Hlusička bbbaea803b Basic db impl
2026-01-24 21:12:25 +01:00

105 lines
3.4 KiB
Rust

// #![cfg_attr(not(feature = "simulator"), no_main)]
use core::{
iter::Chain,
ops::{Deref, DerefMut, Range},
};
use alloc::{borrow::Cow, boxed::Box, ffi::CString, vec::Vec};
use ekv::{Database, MountError, flash::PageID};
use embassy_embedded_hal::{adapter::BlockingAsync, flash::partition::Partition};
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex};
use embassy_time::{Duration, Instant};
use embedded_storage_async::nor_flash::{NorFlash, ReadNorFlash};
use esp_hal::rng::Trng;
use esp_storage::FlashStorage;
use itertools::Itertools;
use log::{info, warn};
use rmk::futures::TryFutureExt;
use slint::SharedString;
use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreKeyPurpose, SpectreUserKey};
#[cfg(feature = "limit-fps")]
use crate::FRAME_DURATION_MIN;
use crate::{
SIGNAL_LCD_SUBMIT, SIGNAL_UI_RENDER,
db::{AcidDatabase, PartitionAcid},
ui::backend::SlintBackend,
util::DurationExt,
};
pub mod backend;
pub mod window_adapter;
slint::include_modules!();
#[embassy_executor::task]
pub async fn run_renderer_task(backend: SlintBackend, flash_part_acid: PartitionAcid) {
let db = AcidDatabase::mount(flash_part_acid).await;
let write = db.write_transaction().await;
// TODO:
// * Store a config as a versioned postcard-serialized struct
// * Store accounts and sites as ranges in the DB
slint::platform::set_platform(Box::new(backend)).expect("backend already initialized");
let main = AppWindow::new().unwrap();
main.on_accepted(|string| {
warn!("Accepted: {string}");
let Ok(c_string) = CString::new(&*string) else {
warn!("String cannot be converted to a C string: {string:?}");
return;
};
unsafe {
let user_key_start = Instant::now();
let user_key = &*spectre_api_sys::spectre_user_key(
c"test".as_ptr(),
c_string.as_ptr(),
SpectreAlgorithm::Current,
);
let user_key_duration = Instant::now().duration_since(user_key_start);
warn!(
"User key derived in {} seconds:\n{user_key:02x?}",
user_key_duration.display_as_secs()
);
let site_key_start = Instant::now();
let site_key = &*spectre_api_sys::spectre_site_key(
user_key as *const SpectreUserKey,
c"example.org".as_ptr(),
SpectreCounter::Initial,
SpectreKeyPurpose::Authentication,
c"".as_ptr(),
);
let site_key_duration = Instant::now().duration_since(site_key_start);
warn!(
"Site key derived in {} seconds:\n{site_key:02x?}",
site_key_duration.display_as_secs()
);
// TODO: Free memory
}
});
run_event_loop(main).await;
}
/// Instead of having a `loop` in the non-async `SlintBackend::run_event_loop`, we achieve
/// async by having only one iteration of the loop run, and `await`ing here.
/// The following block is analogous to `main.run()`.
async fn run_event_loop(main: AppWindow) {
main.show().unwrap();
loop {
slint::run_event_loop().unwrap();
SIGNAL_LCD_SUBMIT.signal(());
#[cfg(feature = "limit-fps")]
embassy_time::Timer::after(FRAME_DURATION_MIN).await;
SIGNAL_UI_RENDER.wait().await;
}
#[expect(unreachable_code)]
main.hide().unwrap();
}