summaryrefslogtreecommitdiffstats
path: root/quantum/secure.c
blob: f07f6af2cb289b6ddd41681850959e9bd473a678 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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);
}