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

canokeys / canokey-core / 9437467744

09 Jun 2024 03:00PM UTC coverage: 79.023% (-0.05%) from 79.071%
9437467744

push

github

web-flow
Merge pull request #88 from canokeys/wip/fix-u2f-touch

Bug fix: touch event being consumed by "pass" before "u2f"

2 of 17 new or added lines in 2 files covered. (11.76%)

1 existing line in 1 file now uncovered.

6502 of 8228 relevant lines covered (79.02%)

549.85 hits per line

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

47.66
/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; }
807✔
18

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

26
bool device_allow_kbd_touch(void) {
NEW
27
  uint32_t now = device_get_tick();
×
NEW
28
  if (!device_is_blinking() &&      // applets are not waiting for touch
×
NEW
29
      now > 2000   &&               // ignore touch for the first 2 seconds
×
NEW
30
      now - 1000 > last_blink &&
×
NEW
31
      get_touch_result() != TOUCH_NO
×
32
  ) {
NEW
33
    DBG_MSG("now=%lu last_blink=%lu\n", now, last_blink);
×
NEW
34
    return true;
×
35
  }
NEW
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();
389✔
42
#endif
43
  return touch_result;
389✔
44
}
45

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

48
uint8_t wait_for_user_presence(uint8_t entry) {
49
  start_blinking(0);
353✔
50
  uint32_t start = device_get_tick();
353✔
51
  uint32_t last = start;
353✔
52
  DBG_MSG("start %u\n", start);
353✔
53

54
  wait_status_t shallow = wait_status;
353✔
55
  if (wait_status == WAIT_NONE) {
353✔
56
    switch (entry) {
353✔
57
    case WAIT_ENTRY_CCID:
4✔
58
      wait_status = WAIT_CCID;
4✔
59
      break;
4✔
60
    case WAIT_ENTRY_CTAPHID:
349✔
61
      wait_status = WAIT_CTAPHID;
349✔
62
      break;
349✔
63
    }
64
  } else
65
    wait_status = WAIT_DEEP;
×
66
  while (get_touch_result() == TOUCH_NO) {
353✔
67
    if (wait_status == WAIT_DEEP_TOUCHED || wait_status == WAIT_DEEP_CANCEL) break;
×
68
    if (wait_status == WAIT_CTAPHID) CCID_Loop();
×
69
    if (CTAPHID_Loop(wait_status != WAIT_CCID) == LOOP_CANCEL) {
×
70
      DBG_MSG("Cancelled by host\n");
×
71
      if (wait_status != WAIT_DEEP) {
×
72
        stop_blinking();
×
73
        wait_status = WAIT_NONE; // namely shallow
×
74
      } else
75
        wait_status = WAIT_DEEP_CANCEL;
×
76
      return USER_PRESENCE_CANCEL;
×
77
    }
78
    uint32_t now = device_get_tick();
×
79
    if (now - start >= 30000) {
×
80
      DBG_MSG("timeout at %u\n", now);
×
81
      if (wait_status != WAIT_DEEP) stop_blinking();
×
82
      wait_status = shallow;
×
83
      return USER_PRESENCE_TIMEOUT;
×
84
    }
85
    if (now - last >= 100) {
×
86
      last = now;
×
87
      if (wait_status != WAIT_CCID) CTAPHID_SendKeepAlive(KEEPALIVE_STATUS_UPNEEDED);
×
88
    }
89
  }
90
  set_touch_result(TOUCH_NO);
353✔
91
  if (wait_status != WAIT_DEEP) stop_blinking();
353✔
92
  if (wait_status == WAIT_DEEP)
353✔
93
    wait_status = WAIT_DEEP_TOUCHED;
×
94
  else if (wait_status == WAIT_DEEP_CANCEL) {
353✔
95
    wait_status = WAIT_NONE;
×
96
    return USER_PRESENCE_TIMEOUT;
×
97
  } else
98
    wait_status = WAIT_NONE;
353✔
99
  return USER_PRESENCE_OK;
353✔
100
}
101

102
int send_keepalive_during_processing(uint8_t entry) {
103
  if (entry == WAIT_ENTRY_CTAPHID) CTAPHID_SendKeepAlive(KEEPALIVE_STATUS_PROCESSING);
534✔
104
  DBG_MSG("KEEPALIVE\n");
534✔
105
  return 0;
534✔
106
}
107

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

131
void set_nfc_state(uint8_t val) { has_rf = val; }
1,538✔
132

133
uint8_t is_nfc(void) {
134
#ifdef TEST // read NFC emulation config from a file
135
  testmode_get_is_nfc_mode();
1,541✔
136
#endif
137
  return has_rf;
1,541✔
138
}
139

140
static void toggle_led(void) {
418✔
141
  if (led_status == ON) {
418✔
142
    led_off();
416✔
143
    led_status = OFF;
416✔
144
  } else {
145
    led_on();
2✔
146
    led_status = ON;
2✔
147
  }
148
}
418✔
149

150
void device_update_led(void) {
151
  uint32_t now = device_get_tick();
×
NEW
152
  if (!device_is_blinking()) return;
×
153
  if (now > blink_timeout) stop_blinking();
×
NEW
154
  else if (now >= last_blink && now - last_blink >= blink_interval) {
×
155
    last_blink = now;
×
156
    toggle_led();
×
157
  }
158
}
159

160
void start_blinking_interval(uint8_t sec, uint32_t interval) {
161
  if (device_is_blinking()) return;
418✔
162
  last_blink = device_get_tick();
418✔
163
  blink_interval = interval;
418✔
164
  if (sec == 0) {
418✔
165
    blink_timeout = UINT32_MAX;
382✔
166
  } else {
167
    blink_timeout = last_blink + sec * 1000;
36✔
168
  }
169
  toggle_led();
418✔
170
}
171

172
void stop_blinking(void) {
173
  blink_timeout = 0;
2,003✔
174
  if (cfg_is_led_normally_on()) {
2,003✔
175
    led_on();
1,991✔
176
    led_status = ON;
1,991✔
177
  } else {
178
    led_off();
12✔
179
    led_status = OFF;
12✔
180
  }
181
}
2,003✔
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