Make button presence async

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2026-08-24 20:08:42 +02:00
parent 7c5f4d9b95
commit 6ffbe463cb
5 changed files with 78 additions and 62 deletions
+63 -47
View File
@@ -35,6 +35,13 @@ extern void execute_tasks(void);
int (*button_pressed_cb)(uint8_t) = NULL;
static bool req_button_pending = false;
#ifndef ENABLE_EMULATION
static bool async_button_wait = false;
static bool async_button_pressed = false;
static uint32_t async_button_started = 0;
static uint32_t async_button_timeout = 0;
static uint32_t async_button_led_mode = MODE_MOUNTED;
#endif
bool is_req_button_pending(void) {
return req_button_pending;
@@ -101,17 +108,16 @@ static uint32_t button_hold_started = 0;
static uint32_t button_last_poll = 0;
volatile uint32_t button_pressed_duration = 0;
int button_wait(void) {
void button_wait_start(void) {
/* Disabled by default. As LED may not be properly configured,
it will not be possible to indicate button press unless it
is commissioned. */
uint32_t button_timeout = 0;
if (phy_data.up_btn_present) {
button_timeout = phy_data.up_btn * 1000;
}
uint32_t button_timeout = phy_data.up_btn_present ? phy_data.up_btn * 1000 : 0;
if (button_timeout == 0 && !force_button_wait) {
signal_emit(SIGNAL_USER_PRESENCE_COMPLETED);
return 0;
uint32_t flag = EV_BUTTON_PRESSED;
queue_try_add(&usb_to_card_q, &flag);
return;
}
if (button_timeout == 0) {
button_timeout = 30000;
@@ -120,55 +126,61 @@ int button_wait(void) {
.timeout = button_timeout / 1000,
};
signal_emit_param(SIGNAL_USER_PRESENCE_REQUEST, &data);
uint32_t start_button = board_millis();
const uint32_t button_poll_interval_ms = 2;
uint32_t next_button_poll_ms = start_button;
bool button_pressed = picok_board_button_read();
bool timeout = false;
cancel_button = false;
uint32_t led_mode = led_get_mode();
led_set_mode(MODE_BUTTON);
async_button_wait = true;
async_button_pressed = picok_board_button_read();
async_button_started = board_millis();
async_button_timeout = button_timeout;
async_button_led_mode = led_get_mode();
req_button_pending = true;
while (button_pressed == false && cancel_button == false) {
execute_tasks();
uint32_t now = board_millis();
if (now >= next_button_poll_ms) {
button_pressed = picok_board_button_read();
next_button_poll_ms = now + button_poll_interval_ms;
}
//sleep_ms(10);
if (start_button + button_timeout < now) { /* timeout */
timeout = true;
break;
}
led_set_mode(MODE_BUTTON);
}
void button_wait_poll(void) {
if (!async_button_wait) {
return;
}
if (!timeout) {
while (button_pressed == true && cancel_button == false) {
execute_tasks();
uint32_t now = board_millis();
if (now >= next_button_poll_ms) {
button_pressed = picok_board_button_read();
next_button_poll_ms = now + button_poll_interval_ms;
}
//sleep_ms(10);
if (start_button + 15000 < now) { /* timeout */
timeout = true;
break;
}
}
bool pressed = picok_board_button_read();
uint32_t now = board_millis();
if (!async_button_pressed && pressed) {
async_button_pressed = true;
}
led_set_mode(led_mode);
button_event_t result = BUTTON_EV_NONE;
if (cancel_button) {
result = BUTTON_EV_CANCELLED;
}
else if (async_button_started + async_button_timeout < now || (async_button_pressed && async_button_started + 15000 < now)) {
result = BUTTON_EV_TIMEOUT;
}
else if (async_button_pressed && !pressed) {
result = BUTTON_EV_PRESSED;
}
if (result == BUTTON_EV_NONE) {
return;
}
async_button_wait = false;
req_button_pending = false;
if (timeout) {
led_set_mode(async_button_led_mode);
uint32_t flag = 0;
if (result == BUTTON_EV_PRESSED) {
flag = EV_BUTTON_PRESSED;
}
else if (result == BUTTON_EV_TIMEOUT) {
flag = EV_BUTTON_TIMEOUT;
}
else if (result == BUTTON_EV_CANCELLED) {
flag = EV_BUTTON_CANCELLED;
}
queue_try_add(&usb_to_card_q, &flag);
if (result == BUTTON_EV_PRESSED) {
signal_emit(SIGNAL_USER_PRESENCE_COMPLETED);
}
else if (result == BUTTON_EV_TIMEOUT) {
signal_emit(SIGNAL_USER_PRESENCE_TIMEOUT);
return 1;
}
else if (cancel_button) {
else {
signal_emit(SIGNAL_USER_PRESENCE_CANCELLED);
return 2;
}
signal_emit(SIGNAL_USER_PRESENCE_COMPLETED);
return 0;
}
#endif
@@ -176,7 +188,7 @@ int button_wait(void) {
void button_task(void) {
#ifndef ENABLE_EMULATION
uint32_t now = board_millis();
if (now > 1000 && now - button_last_poll >= 10 && !is_busy()) { // wait 1 second to boot up
if (now > 1000 && now - button_last_poll >= 10 && (async_button_wait || !is_busy())) { // wait 1 second to boot up
#ifdef PICO_PLATFORM
if (!multicore_lockout_start_timeout_us(1000)) {
return;
@@ -187,6 +199,10 @@ void button_task(void) {
multicore_lockout_end_timeout_us(1000);
#endif
button_last_poll = now;
if (async_button_wait) {
button_wait_poll();
return;
}
if (current_button_state && !button_hold_state) {
button_hold_started = now;
button_pressed_duration = 0;
+13 -1
View File
@@ -25,11 +25,23 @@
#define BOOT_PIN GPIO_NUM_0
#endif
extern int button_wait(void);
typedef enum {
BUTTON_EV_PRESSED,
BUTTON_EV_TIMEOUT,
BUTTON_EV_CANCELLED,
BUTTON_EV_NONE,
} button_event_t;
extern void button_wait_start(void);
extern void button_wait_poll(void);
extern volatile uint32_t button_pressed_duration;
extern void button_task(void);
extern volatile bool cancel_button;
extern bool touch_accept_button;
extern volatile bool force_button_wait;
extern int (*button_pressed_cb)(uint8_t);
extern bool is_req_button_pending(void);
#endif // BUTTON_H
-4
View File
@@ -149,10 +149,6 @@ static inline uint32_t put_uint64_le(uint64_t n, uint8_t *b) {
return 8;
}
extern int (*button_pressed_cb)(uint8_t);
extern bool is_req_button_pending(void);
#define PICOKEYS_OK 0
#define PICOKEYS_ERR_NO_MEMORY -1000
#define PICOKEYS_ERR_MEMORY_FATAL -1001
+1 -1
View File
@@ -31,6 +31,7 @@ static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED;
#include "picokeys_version.h"
#include "apdu.h"
#include "usb.h"
#include "button.h"
extern void init_fido(void);
bool is_nk = false;
@@ -331,7 +332,6 @@ static uint32_t allocate_cid(void) {
}
uint8_t thread_type = 0; //1 is APDU, 2 is CBOR
extern volatile bool cancel_button;
extern int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len);
static uint32_t last_keepalive_time = 0;
+1 -9
View File
@@ -350,15 +350,7 @@ int card_status(uint8_t itf) {
}
#ifndef ENABLE_EMULATION
else if (m == EV_PRESS_BUTTON) {
int ret = button_wait();
uint32_t flag = EV_BUTTON_PRESSED;
if (ret == 1) { //timeout
flag = EV_BUTTON_TIMEOUT;
}
else if (ret == 2) { //cancelled
flag = EV_BUTTON_CANCELLED;
}
queue_try_add(&usb_to_card_q, &flag);
button_wait_start();
}
#endif
#ifdef PICO_PLATFORM