summaryrefslogtreecommitdiffstats
path: root/quantum/secure.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/secure.c')
-rw-r--r--quantum/secure.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/quantum/secure.c b/quantum/secure.c
new file mode 100644
index 0000000000..f07f6af2cb
--- /dev/null
+++ b/quantum/secure.c
@@ -0,0 +1,102 @@
+// Copyright 2022 QMK
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "secure.h"
+#include "timer.h"
+
+#ifndef SECURE_UNLOCK_TIMEOUT
+# define SECURE_UNLOCK_TIMEOUT 5000
+#endif
+
+#ifndef SECURE_IDLE_TIMEOUT
+# define SECURE_IDLE_TIMEOUT 60000
+#endif
+
+#ifndef SECURE_UNLOCK_SEQUENCE
+# define SECURE_UNLOCK_SEQUENCE \
+ { \
+ { 0, 0 } \
+ }
+#endif
+
+static secure_status_t secure_status = SECURE_LOCKED;
+static uint32_t unlock_time = 0;
+static uint32_t idle_time = 0;
+
+static void secure_hook(secure_status_t secure_status) {
+ secure_hook_quantum(secure_status);
+ secure_hook_kb(secure_status);
+}
+
+secure_status_t secure_get_status(void) {
+ return secure_status;
+}
+
+void secure_lock(void) {
+ secure_status = SECURE_LOCKED;
+ secure_hook(secure_status);
+}
+
+void secure_unlock(void) {
+ secure_status = SECURE_UNLOCKED;
+ idle_time = timer_read32();
+ secure_hook(secure_status);
+}
+
+void secure_request_unlock(void) {
+ if (secure_status == SECURE_LOCKED) {
+ secure_status = SECURE_PENDING;
+ unlock_time = timer_read32();
+ }
+ secure_hook(secure_status);
+}
+
+void secure_activity_event(void) {
+ if (secure_status == SECURE_UNLOCKED) {
+ idle_time = timer_read32();
+ }
+}
+
+void secure_keypress_event(uint8_t row, uint8_t col) {
+ static const uint8_t sequence[][2] = SECURE_UNLOCK_SEQUENCE;
+ static const uint8_t sequence_len = sizeof(sequence) / sizeof(sequence[0]);
+
+ static uint8_t offset = 0;
+ if ((sequence[offset][0] == row) && (sequence[offset][1] == col)) {
+ offset++;
+ if (offset == sequence_len) {
+ offset = 0;
+ secure_unlock();
+ }
+ } else {
+ offset = 0;
+ secure_lock();
+ }
+}
+
+void secure_task(void) {
+#if SECURE_UNLOCK_TIMEOUT != 0
+ // handle unlock timeout
+ if (secure_status == SECURE_PENDING) {
+ if (timer_elapsed32(unlock_time) >= SECURE_UNLOCK_TIMEOUT) {
+ secure_lock();
+ }
+ }
+#endif
+
+#if SECURE_IDLE_TIMEOUT != 0
+ // handle idle timeout
+ if (secure_status == SECURE_UNLOCKED) {
+ if (timer_elapsed32(idle_time) >= SECURE_IDLE_TIMEOUT) {
+ secure_lock();
+ }
+ }
+#endif
+}
+
+__attribute__((weak)) bool secure_hook_user(secure_status_t secure_status) {
+ return true;
+}
+__attribute__((weak)) bool secure_hook_kb(secure_status_t secure_status) {
+ return secure_hook_user(secure_status);
+}