Basic TOTP viewer

This commit is contained in:
FliegendeWurst 2023-10-12 15:35:00 +02:00
parent 6335eb818e
commit 30683b42f0
7 changed files with 386 additions and 39 deletions

236
Cargo.lock generated
View File

@ -37,13 +37,28 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "1.1.1"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "andotp-import"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89e4375a7f794f05aaaf899b684307a837fd73c773888cbb01a0f622eed59e43"
dependencies = [
"byteorder",
"ring",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"totp-rs",
]
[[package]]
name = "android-activity"
version = "0.4.3"
@ -113,6 +128,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973"
[[package]]
name = "base32"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa"
[[package]]
name = "base64"
version = "0.21.4"
@ -143,6 +164,15 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "block-sys"
version = "0.1.0-beta.1"
@ -191,14 +221,14 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
name = "byteorder"
version = "1.4.3"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "calloop"
@ -292,6 +322,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "constant_time_eq"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6"
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -345,6 +381,15 @@ dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
@ -393,6 +438,16 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "ctor"
version = "0.2.5"
@ -400,7 +455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583"
dependencies = [
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
@ -409,6 +464,17 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@ -644,7 +710,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
@ -668,6 +734,16 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "gethostname"
version = "0.3.0"
@ -774,6 +850,15 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "human-sort"
version = "0.2.2"
@ -900,9 +985,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.26"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
@ -939,9 +1024,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.148"
version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "libloading"
@ -1235,9 +1320,9 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
@ -1281,7 +1366,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
@ -1439,9 +1524,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.67"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
@ -1501,6 +1586,7 @@ dependencies = [
name = "raspi-oled"
version = "0.1.0"
dependencies = [
"andotp-import",
"display-interface-spi",
"embedded-graphics",
"embedded-hal 0.2.7",
@ -1509,6 +1595,7 @@ dependencies = [
"libc",
"linux-embedded-hal",
"rand_xoshiro",
"rpassword",
"rppal",
"rusqlite",
"serde",
@ -1518,6 +1605,7 @@ dependencies = [
"ssd1351",
"time",
"time-tz",
"totp-rs",
"ureq",
"winit",
]
@ -1559,9 +1647,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.9.6"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
checksum = "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87"
dependencies = [
"aho-corasick",
"memchr",
@ -1571,9 +1659,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.3.9"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
checksum = "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b"
dependencies = [
"aho-corasick",
"memchr",
@ -1582,9 +1670,34 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.7.5"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
checksum = "56d84fdd47036b038fc80dd333d10b6aab10d5d31f4a366e20014def75328d33"
[[package]]
name = "ring"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e"
dependencies = [
"cc",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys 0.48.0",
]
[[package]]
name = "rpassword"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322"
dependencies = [
"libc",
"rtoolbox",
"winapi",
]
[[package]]
name = "rppal"
@ -1601,6 +1714,16 @@ dependencies = [
"void",
]
[[package]]
name = "rtoolbox"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "rusqlite"
version = "0.27.0"
@ -1676,7 +1799,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
@ -1711,6 +1834,28 @@ dependencies = [
"termios",
]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
@ -1850,6 +1995,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "1.0.109"
@ -1863,9 +2014,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.37"
version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [
"proc-macro2",
"quote",
@ -1907,7 +2058,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
]
[[package]]
@ -2034,6 +2185,19 @@ dependencies = [
"winnow",
]
[[package]]
name = "totp-rs"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3504f96adf86d28e7eb16fa236a7951ec72c15ee100d1b5318e225944bc8cb"
dependencies = [
"base32",
"constant_time_eq",
"hmac",
"sha1",
"sha2",
]
[[package]]
name = "tracing"
version = "0.1.37"
@ -2057,6 +2221,12 @@ version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
version = "0.3.13"
@ -2078,6 +2248,12 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.8.0"
@ -2152,7 +2328,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
"wasm-bindgen-shared",
]
@ -2174,7 +2350,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.37",
"syn 2.0.38",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -2533,9 +2709,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.5.15"
version = "0.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907"
dependencies = [
"memchr",
]

View File

@ -26,6 +26,9 @@ winit = { version = "0.28.7", optional = true }
softbuffer = { version = "0.3.1", optional = true }
rand_xoshiro = "0.6.0"
gpiocdev = "0.6.0"
rpassword = "7.2.0"
andotp-import = "0.1.0"
totp-rs = "5.4.0"
#gpio-am2302-rs = { git = "https://github.com/FliegendeWurst/gpio-am2302-rs" }
[features]

View File

@ -1,4 +1,4 @@
use std::{fs, ops::Sub, sync::atomic::AtomicBool, time::Duration};
use std::{any::Any, fs, ops::Sub, sync::atomic::AtomicBool, time::Duration};
use embedded_graphics::{
image::ImageRaw,
@ -419,4 +419,12 @@ impl<D: DrawTarget<Color = Rgb565>> Draw<D> for Measurements {
fn draw(&self, disp: &mut D, rng: &mut crate::Rng) -> Result<bool, <D as DrawTarget>::Error> {
panic!("draw without ctx");
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}

View File

@ -1,2 +1,4 @@
mod measurements;
pub use measurements::Measurements;
mod totp;
pub use totp::Totp;

111
src/bin/draw/totp.rs Normal file
View File

@ -0,0 +1,111 @@
use std::{any::Any, cell::RefCell};
use andotp_import::Account;
use embedded_graphics::{
mono_font::{
ascii::{FONT_10X20, FONT_9X15},
MonoTextStyleBuilder,
},
pixelcolor::Rgb565,
prelude::*,
text::Text,
Drawable,
};
use totp_rs::TOTP;
use crate::{screensaver::Screensaver, Context, ContextDefault, Draw, BLACK};
#[derive(Debug, Clone)]
pub struct Totp {
codes: RefCell<Vec<String>>,
secrets: Vec<(Account, TOTP)>,
page: usize,
}
impl Totp {
pub fn new(secrets: Vec<(Account, TOTP)>) -> Self {
Self {
codes: RefCell::new(vec![]),
secrets,
page: 0,
}
}
pub fn next_page(&mut self) {
self.page += 1;
}
}
impl<D: DrawTarget<Color = Rgb565>> Screensaver<D> for Totp {
fn id(&self) -> &'static str {
"totp"
}
fn convert_draw(&self) -> Box<dyn Draw<D>> {
Box::new(Totp {
codes: RefCell::new(vec![]),
secrets: self.secrets.clone(),
page: 0,
})
}
}
impl<D: DrawTarget<Color = Rgb565>> Draw<D> for Totp {
fn draw(&self, disp: &mut D, _rng: &mut crate::Rng) -> Result<bool, <D as DrawTarget>::Error> {
let codes: Vec<_> = self
.secrets
.iter()
.skip(self.page * 6)
.take(6)
.map(|x| (&x.0.issuer, &x.0.label, x.1.generate_current().unwrap()))
.collect();
if codes.len() == self.codes.borrow().len()
&& codes.iter().zip(self.codes.borrow().iter()).all(|(x, y)| &x.2 == y)
{
return Ok(false);
}
*self.codes.borrow_mut() = codes.iter().map(|x| x.2.clone()).collect();
disp.clear(BLACK)?;
let mut y = 16;
let text_style_code = MonoTextStyleBuilder::new()
.font(&FONT_10X20)
.text_color(Rgb565::new(0xff, 0xff, 0xff))
.build();
let text_style_label = MonoTextStyleBuilder::new()
.font(&FONT_9X15)
.text_color(Rgb565::new(0xff, 0xff, 0xff))
.build();
for (issuer, label, code) in codes {
Text::new(&code, Point::new(0, y), text_style_code).draw(disp)?;
let label_text = if issuer != "" {
issuer
} else if let Some((issuer, _label)) = label.split_once(" - ") {
issuer
} else {
label
};
Text::new(
if label_text.len() > 7 {
&label_text[0..7]
} else {
label_text
},
Point::new(60, y),
text_style_label,
)
.draw(disp)?;
y += 20 + 1;
}
Ok(true)
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}

View File

@ -1,7 +1,9 @@
#![feature(array_windows, round_char_boundary)]
use std::{
any::Any,
cell::RefCell,
env,
rc::Rc,
thread,
time::{Duration, Instant},
@ -9,6 +11,7 @@ use std::{
use action::Action;
use display_interface_spi::SPIInterfaceNoCS;
use draw::Totp;
use embedded_graphics::{pixelcolor::Rgb565, prelude::DrawTarget};
use gpiocdev::line::{Bias, EdgeDetection, Value};
use rand_xoshiro::{rand_core::SeedableRng, Xoroshiro128StarStar};
@ -75,6 +78,10 @@ impl<D: DrawTarget<Color = Rgb565>> ContextDefault<D> {
}
}
fn add(&mut self, totp: Totp) {
self.screensavers.push(Box::new(totp));
}
fn loop_iter(&mut self, disp: &mut D, rng: &mut Rng) -> bool {
let time = OffsetDateTime::now_utc().to_timezone(BERLIN);
// check schedules
@ -138,7 +145,7 @@ fn pc_main() {}
#[cfg(feature = "pc")]
fn pc_main() {
use std::{env, num::NonZeroU32};
use std::num::NonZeroU32;
use winit::{
dpi::LogicalSize,
@ -173,7 +180,12 @@ fn pc_main() {
let mut buffer_dirty = true;
let mut ctx = ContextDefault::new();
ctx.do_action(Action::Screensaver("measurements"));
if args.iter().any(|x| x == "--totp") {
let pw = rpassword::prompt_password("TOTP password: ").unwrap();
let totps = andotp_import::read_from_file("./otp_accounts_2023-10-02_18-58-25.json.aes", &pw).unwrap();
ctx.add(Totp::new(totps));
ctx.do_action(Action::Screensaver("totp"));
}
let mut rng = Xoroshiro128StarStar::seed_from_u64(17381);
event_loop.run(move |event, _, control_flow| {
@ -242,16 +254,20 @@ fn pc_main() {
}
pub trait Draw<D: DrawTarget<Color = Rgb565>> {
fn draw_with_ctx(&self, ctx: &ContextDefault<D>, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error> {
fn draw_with_ctx(&self, _ctx: &ContextDefault<D>, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error> {
self.draw(disp, rng)
}
fn draw(&self, disp: &mut D, rng: &mut Rng) -> Result<bool, D::Error>;
fn expired(&self) -> bool {
false
}
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
fn rpi_main() {
let args: Vec<_> = env::args().map(|x| x.to_string()).collect();
let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 19660800, Mode::Mode0).unwrap();
let gpio = Gpio::new().unwrap();
let dc = gpio.get(25).unwrap().into_output();
@ -268,7 +284,14 @@ fn rpi_main() {
// Init PWM handling
let pwm = thread::spawn(handle_pwm);
main_loop(disp);
let mut ctx = ContextDefault::new();
if args.iter().any(|x| x == "--totp") {
let pw = rpassword::prompt_password("TOTP password: ").unwrap();
let totps = andotp_import::read_from_file("./otp_accounts_2023-10-02_18-58-25.json.aes", &pw).unwrap();
ctx.add(Totp::new(totps));
}
main_loop(disp, ctx);
let _ = pwm.join();
}
@ -296,10 +319,9 @@ fn handle_pwm() {
}
}
fn main_loop(mut disp: Oled) {
fn main_loop(mut disp: Oled, mut ctx: ContextDefault<Oled>) {
disp.clear(BLACK).unwrap();
let mut ctx = ContextDefault::new();
let mut rng = Xoroshiro128StarStar::seed_from_u64(17381);
let mut last_button = Instant::now();
@ -368,11 +390,19 @@ fn main_loop(mut disp: Oled) {
let _ = ctx.pop_action_and_clear(&mut disp);
disable_pwm().unwrap();
let _ = disp.flush();
clear = true;
}
},
[3] => {},
[3] => {
ctx.do_action(Action::Screensaver("totp"));
},
[3, 1] => {
enable_pwm().unwrap();
if let Some(x) = ctx.active.borrow_mut().last_mut() {
let totp: Option<&mut Totp> = x.as_any_mut().downcast_mut();
if let Some(x) = totp {
x.next_page();
}
}
pop_last = true;
},
[3, 2] => {

View File

@ -1,3 +1,4 @@
use std::any::Any;
use std::cell::RefCell;
use std::sync::atomic::{AtomicU32, AtomicU64};
@ -80,6 +81,14 @@ impl<D: DrawTarget<Color = Rgb565>> Draw<D> for SimpleScreensaver {
fn expired(&self) -> bool {
self.iters.load(std::sync::atomic::Ordering::Relaxed) > 1000
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl SimpleScreensaver {
@ -158,6 +167,14 @@ impl<D: DrawTarget<Color = Rgb565>> Draw<D> for TimeDisplay {
.draw(disp)?;
Ok(true)
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
pub static STAR: SimpleScreensaver = SimpleScreensaver::new("star", include_bytes!("./star.raw"));