You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
3.1 KiB
162 lines
3.1 KiB
#include "keyd.h" |
|
|
|
#define MAX_AUX_FDS 32 |
|
|
|
static int aux_fds[MAX_AUX_FDS]; |
|
static size_t nr_aux_fds = 0; |
|
|
|
struct device device_table[MAX_DEVICES]; |
|
size_t device_table_sz; |
|
|
|
static void panic_check(uint8_t code, uint8_t pressed) |
|
{ |
|
static uint8_t enter, backspace, escape; |
|
switch (code) { |
|
case KEYD_ENTER: |
|
enter = pressed; |
|
break; |
|
case KEYD_BACKSPACE: |
|
backspace = pressed; |
|
break; |
|
case KEYD_ESC: |
|
escape = pressed; |
|
break; |
|
} |
|
|
|
if (backspace && enter && escape) |
|
die("panic sequence detected"); |
|
} |
|
|
|
static long get_time_ms() |
|
{ |
|
struct timespec ts; |
|
clock_gettime(CLOCK_MONOTONIC, &ts); |
|
return ts.tv_sec * 1E3 + ts.tv_nsec / 1E6; |
|
} |
|
|
|
int evloop(int (*event_handler) (struct event *ev)) |
|
{ |
|
size_t i; |
|
int timeout = 0; |
|
int monfd; |
|
|
|
struct pollfd pfds[MAX_DEVICES+MAX_AUX_FDS+1]; |
|
|
|
struct event ev; |
|
|
|
monfd = devmon_create(); |
|
device_table_sz = device_scan(device_table); |
|
|
|
for (i = 0; i < device_table_sz; i++) { |
|
ev.type = EV_DEV_ADD; |
|
ev.dev = &device_table[i]; |
|
|
|
event_handler(&ev); |
|
} |
|
|
|
while (1) { |
|
int removed = 0; |
|
|
|
int start_time; |
|
int elapsed; |
|
|
|
pfds[0].fd = monfd; |
|
pfds[0].events = POLLIN; |
|
|
|
for (i = 0; i < device_table_sz; i++) { |
|
pfds[i+1].fd = device_table[i].fd; |
|
pfds[i+1].events = POLLIN | POLLERR; |
|
} |
|
|
|
for (i = 0; i < nr_aux_fds; i++) { |
|
pfds[i+device_table_sz+1].fd = aux_fds[i]; |
|
pfds[i+device_table_sz+1].events = POLLIN | POLLERR; |
|
} |
|
|
|
start_time = get_time_ms(); |
|
poll(pfds, device_table_sz+nr_aux_fds+1, timeout > 0 ? timeout : -1); |
|
ev.timestamp = get_time_ms(); |
|
elapsed = ev.timestamp - start_time; |
|
|
|
if (timeout > 0 && elapsed >= timeout) { |
|
ev.type = EV_TIMEOUT; |
|
ev.dev = NULL; |
|
ev.devev = NULL; |
|
timeout = event_handler(&ev); |
|
} else { |
|
timeout -= elapsed; |
|
} |
|
|
|
for (i = 0; i < device_table_sz; i++) { |
|
if (pfds[i+1].revents) { |
|
struct device_event *devev; |
|
|
|
while ((devev = device_read_event(&device_table[i]))) { |
|
if (devev->type == DEV_REMOVED) { |
|
ev.type = EV_DEV_REMOVE; |
|
ev.dev = &device_table[i]; |
|
|
|
timeout = event_handler(&ev); |
|
|
|
device_table[i].fd = -1; |
|
removed = 1; |
|
break; |
|
} else { |
|
//Handle device event |
|
panic_check(devev->code, devev->pressed); |
|
|
|
ev.type = EV_DEV_EVENT; |
|
ev.devev = devev; |
|
ev.dev = &device_table[i]; |
|
|
|
timeout = event_handler(&ev); |
|
} |
|
} |
|
} |
|
} |
|
|
|
for (i = 0; i < nr_aux_fds; i++) { |
|
short events = pfds[i+device_table_sz+1].revents; |
|
|
|
if (events) { |
|
ev.type = events & POLLERR ? EV_FD_ERR : EV_FD_ACTIVITY; |
|
ev.fd = aux_fds[i]; |
|
|
|
timeout = event_handler(&ev); |
|
} |
|
} |
|
|
|
|
|
if (pfds[0].revents) { |
|
struct device dev; |
|
|
|
while (devmon_read_device(monfd, &dev) == 0) { |
|
assert(device_table_sz < MAX_DEVICES); |
|
device_table[device_table_sz++] = dev; |
|
|
|
ev.type = EV_DEV_ADD; |
|
ev.dev = &device_table[device_table_sz-1]; |
|
|
|
timeout = event_handler(&ev); |
|
} |
|
} |
|
|
|
if (removed) { |
|
size_t n = 0; |
|
for (i = 0; i < device_table_sz; i++) { |
|
if (device_table[i].fd != -1) |
|
device_table[n++] = device_table[i]; |
|
} |
|
device_table_sz = n; |
|
} |
|
|
|
} |
|
|
|
return 0; |
|
} |
|
|
|
void evloop_add_fd(int fd) |
|
{ |
|
assert(nr_aux_fds < MAX_AUX_FDS); |
|
aux_fds[nr_aux_fds++] = fd; |
|
}
|
|
|