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

#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;
}