• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

canokeys / canokey-core / 12325704235

14 Dec 2024 01:37AM UTC coverage: 78.407% (-0.3%) from 78.707%
12325704235

push

github

web-flow
Merge pull request #107 from canokeys/dev

Fix state of current_cmd_src

2 of 8 new or added lines in 2 files covered. (25.0%)

103 existing lines in 11 files now uncovered.

6467 of 8248 relevant lines covered (78.41%)

571.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.12
/src/device.c
1
// SPDX-License-Identifier: Apache-2.0
2
#include "common.h"
3
#include <admin.h>
4
#include <ccid.h>
5
#include <ctaphid.h>
6
#include <device.h>
7
#include <kbdhid.h>
8
#include <webusb.h>
9

10
volatile static uint8_t touch_result;
11
static uint8_t has_rf;
12
static uint32_t last_blink, blink_timeout, blink_interval;
13
static enum { ON, OFF } led_status;
14
typedef enum { WAIT_NONE = 1, WAIT_CCID, WAIT_CTAPHID, WAIT_DEEP, WAIT_DEEP_TOUCHED, WAIT_DEEP_CANCEL } wait_status_t;
15
volatile static wait_status_t wait_status = WAIT_NONE; // WAIT_NONE is not 0, hence inited
16

17
uint8_t device_is_blinking(void) { return blink_timeout != 0; }
1,250✔
18

19
void device_loop(void) {
20
  CCID_Loop();
×
21
  CTAPHID_Loop(0);
×
22
  WebUSB_Loop();
×
23
  KBDHID_Loop();
×
24
}
×
25

26
bool device_allow_kbd_touch(void) {
27
  uint32_t now = device_get_tick();
×
28
  if (!device_is_blinking() &&      // applets are not waiting for touch
×
29
      now > TOUCH_AFTER_PWRON &&    // ignore touch for some time after power-on
×
30
      now - TOUCH_EXPIRE_TIME > last_blink &&
×
31
      get_touch_result() != TOUCH_NO
×
32
  ) {
33
    DBG_MSG("now=%lu last_blink=%lu\n", now, last_blink);
×
34
    return true;
×
35
  }
36
  return false;
×
37
}
38

39
uint8_t get_touch_result(void) {
40
#ifdef TEST // emulate user interaction in test mode
41
  testmode_emulate_user_presence();
802✔
42
#endif
43
  return touch_result;
802✔
44
}
45

46
void set_touch_result(uint8_t result) { touch_result = result; }
838✔
47

48
uint8_t wait_for_user_presence(uint8_t entry) {
49

50
  if (wait_status == WAIT_NONE) {
383✔
51
    switch (entry) {
383✔
52
    case WAIT_ENTRY_CCID:
383✔
53
      wait_status = WAIT_CCID;
383✔
54
      break;
383✔
UNCOV
55
    case WAIT_ENTRY_CTAPHID:
×
UNCOV
56
      wait_status = WAIT_CTAPHID;
×
UNCOV
57
      break;
×
58
    }
59
  } else {
60
    // New user presence test is denied while a test is ongoing
UNCOV
61
    DBG_MSG("Denied\n");
×
UNCOV
62
    return USER_PRESENCE_TIMEOUT;
×
63
  }
64
  
65
  uint32_t start = device_get_tick();
383✔
66
  uint32_t last = start;
383✔
67
  DBG_MSG("start %u\n", start);
383✔
68
  while (get_touch_result() == TOUCH_NO) {
766✔
69
    // Keep blinking, in case other applet stops it 
70
    start_blinking(0);
383✔
71
    // Nested CCID processing is not allowed
72
    if (entry != WAIT_ENTRY_CCID) CCID_Loop();
383✔
73
    if (CTAPHID_Loop(entry == WAIT_ENTRY_CTAPHID) == LOOP_CANCEL) {
383✔
UNCOV
74
      DBG_MSG("Cancelled by host\n");
×
75
      stop_blinking();
×
76
      wait_status = WAIT_NONE;
×
UNCOV
77
      return USER_PRESENCE_CANCEL;
×
78
    }
79
    uint32_t now = device_get_tick();
383✔
80
    if (now - start >= 30000) {
383✔
81
      DBG_MSG("timeout at %u\n", now);
×
82
      stop_blinking();
×
83
      wait_status = WAIT_NONE;
×
UNCOV
84
      return USER_PRESENCE_TIMEOUT;
×
85
    }
86
    if (now - last >= 100) {
383✔
87
      last = now;
×
UNCOV
88
      if (entry == WAIT_ENTRY_CTAPHID) CTAPHID_SendKeepAlive(KEEPALIVE_STATUS_UPNEEDED);
×
89
    }
90
  }
91
  // Consume this touch event
92
  set_touch_result(TOUCH_NO);
383✔
93
  stop_blinking();
383✔
94
  wait_status = WAIT_NONE;
383✔
95
  return USER_PRESENCE_OK;
383✔
96
}
97

98
int send_keepalive_during_processing(uint8_t entry) {
UNCOV
99
  if (entry == WAIT_ENTRY_CTAPHID) CTAPHID_SendKeepAlive(KEEPALIVE_STATUS_PROCESSING);
×
100
  DBG_MSG("KEEPALIVE\n");
593✔
101
  return 0;
593✔
102
}
103

104
__attribute__((weak)) int strong_user_presence_test(void) {
UNCOV
105
  for (int i = 0; i < 5; i++) {
×
UNCOV
106
    const uint8_t wait_sec = 2;
×
UNCOV
107
    start_blinking_interval(wait_sec, (i & 1) ? 200 : 50);
×
UNCOV
108
    uint32_t now, begin = device_get_tick();
×
109
    bool user_presence = false;
×
110
    do {
111
      if (get_touch_result() == TOUCH_SHORT) {
×
112
        user_presence = true;
×
113
        set_touch_result(TOUCH_NO);
×
UNCOV
114
        stop_blinking();
×
115
        // wait for some time before next user-precense test
116
        begin = device_get_tick();
×
117
      }
118
      now = device_get_tick();
×
UNCOV
119
    } while (now - begin < 1000 * wait_sec);
×
120
    if (!user_presence) {
×
UNCOV
121
      return -1;
×
122
    }
123
  }
124
  return 0;
×
125
}
126

127
void set_nfc_state(uint8_t val) { has_rf = val; }
1,735✔
128

129
uint8_t is_nfc(void) {
130
#ifdef TEST // read NFC emulation config from a file
131
  testmode_get_is_nfc_mode();
1,738✔
132
#endif
133
  return has_rf;
1,738✔
134
}
135

136
static void toggle_led(void) {
448✔
137
  if (led_status == ON) {
448✔
138
    led_off();
446✔
139
    led_status = OFF;
446✔
140
  } else {
141
    led_on();
2✔
142
    led_status = ON;
2✔
143
  }
144
}
448✔
145

146
void device_update_led(void) {
UNCOV
147
  uint32_t now = device_get_tick();
×
UNCOV
148
  if (now > blink_timeout) {
×
UNCOV
149
    stop_blinking();
×
UNCOV
150
  } else if (device_is_blinking() && now >= last_blink && now - last_blink >= blink_interval) {
×
151
    last_blink = now;
×
152
    toggle_led();
×
153
  }
154
}
×
155

156
void start_blinking_interval(uint8_t sec, uint32_t interval) {
157
  if (device_is_blinking()) return;
448✔
158
  last_blink = device_get_tick();
448✔
159
  blink_interval = interval;
448✔
160
  if (sec == 0) {
448✔
161
    blink_timeout = UINT32_MAX;
412✔
162
  } else {
163
    blink_timeout = last_blink + sec * 1000;
36✔
164
  }
165
  toggle_led();
448✔
166
}
167

168
void stop_blinking(void) {
169
  blink_timeout = 0;
2,205✔
170
  if (cfg_is_led_normally_on()) {
2,205✔
171
    led_on();
2,193✔
172
    led_status = ON;
2,193✔
173
  } else {
174
    led_off();
12✔
175
    led_status = OFF;
12✔
176
  }
177
}
2,205✔
178

179
void device_init(void) {
UNCOV
180
  last_blink = 0;
×
UNCOV
181
  stop_blinking();
×
UNCOV
182
  set_touch_result(TOUCH_NO);
×
183
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc