5. DONE Event Polling
CLOSED: [2020-04-05 Sun 22:05] This describes the interface for polling events from the monome (buttons + knobs).
5.1. Opening File Handles
Every peripheral is opened as a file handle. Each knob has a dedicated filehandle. All buttons come from one filehandle.
5.1.1. Opening a Knob
Each knob has their own filehandle for event, so it must be specified which one you want: 1, 2, or 3.
int norns_open_knob(int knob);
int norns_open_knob(int knob)
{
char path[256];
sprintf(path,
"/dev/input/by-path/platform-soc:knob%d-event",
knob);
return open(path, O_RDONLY | O_NONBLOCK);
}
5.1.2. Opening the Keys
The function norns_open_keys
returns the output of open
for opening the keys location.
int norns_open_keys(void);
int norns_open_keys(void)
{
return open("/dev/input/by-path/platform-keys-event",
O_RDONLY | O_NONBLOCK);
}
5.1.3. Callbacks
Every knob + button has a callback function with custom user data. These can be overridden by monolith pages.
5.1.3.1. Knobs Callbacks
5.1.3.2. Buttons Callbacks
5.2. Event Polling Data
5.2.1. typedef + struct
typedef struct norns_poll_d norns_poll_d;
typedef struct {
void *ud;
void (*fun)(void *, int);
} norns_peripheral;
struct norns_poll_d {
int knob_fid[3];
int keys_fid;
norns_peripheral knob[3];
norns_peripheral key[3];
struct input_event evt[8];
};
5.2.2. Allocating/freeing the event poller
Useful when using this as opaque struct.
void norns_poll_new(norns_poll_d **poll);
void norns_poll_del(norns_poll_d **poll);
void norns_poll_new(norns_poll_d **ppoll)
{
norns_poll_d *poll;
poll = calloc(1, sizeof(norns_poll_d));
*ppoll = poll;
}
void norns_poll_del(norns_poll_d **ppoll)
{
free(*ppoll);
}
5.2.3. Event Poller Initilization
Opens all the filehandles, zeros out peripheral callbacks.
void norns_poll_init(norns_poll_d *poll);
void norns_poll_init(norns_poll_d *poll)
{
int i;
poll->keys_fid = norns_open_keys();
for (i = 0; i < 3; i++) {
poll->knob_fid[i] = norns_open_knob(i+1);
/* while we're doing things in 3...*/
poll->knob[i].ud = NULL;
poll->knob[i].fun = NULL;
poll->key[i].ud = NULL;
poll->key[i].fun = NULL;
}
}
5.2.4. Event Poller Cleanup
void norns_poll_clean(norns_poll_d *poll);
void norns_poll_clean(norns_poll_d *poll)
{
int i;
close(poll->keys_fid);
for (i = 0; i < 3; i++) {
close(poll->knob_fid[i]);
}
}
5.3. Polling Function
This function polls all the buttons and knobs from monolith. It is mostly meant to be called inside the main monolith event handler thread.
void norns_poll(norns_poll_d *poll);
void norns_poll(norns_poll_d *poll)
{
int k, e;
int nevts;
int rc;
struct input_event *evt;
/* read knobs */
evt = poll->evt;
for (k = 0; k < 3; k++) {
rc = read(poll->knob_fid[k],
evt,
sizeof(struct input_event) * 8);
if (rc != -1) {
nevts = rc / sizeof(struct input_event);
for (e = 0; e < nevts; e++) {
if (evt[e].type) {
if (poll->knob[k].fun != NULL) {
poll->knob[k].fun(poll->knob[k].ud,
evt[e].value);
}
}
}
}
}
rc = read(poll->keys_fid,
evt,
sizeof(struct input_event) * 8);
/* read keys */
if (rc != -1) {
nevts = rc / sizeof(struct input_event);
for (e = 0; e < nevts; e++) {
if (evt[e].type) {
int val;
int code;
val = evt[e].value;
code = evt[e].code - 1;
if (poll->key[code].fun != NULL) {
poll->key[code].fun(poll->key[code].ud,
val);
}
}
}
}
}
5.4. Setting Event Callbacks
5.4.1. Set Knob
void norns_poll_cb_knob(norns_poll_d *poll,
int knob,
void (*fun)(void *, int),
void *ud);
void norns_poll_cb_knob(norns_poll_d *poll,
int knob,
void (*fun)(void *, int),
void *ud)
{
if (knob < 0 || knob >= 3) return;
poll->knob[knob].fun = fun;
poll->knob[knob].ud = ud;
}
5.4.2. Set Key
void norns_poll_cb_key(norns_poll_d *poll,
int key,
void (*fun)(void *, int),
void *ud);
void norns_poll_cb_key(norns_poll_d *poll,
int key,
void (*fun)(void *, int),
void *ud)
{
if (key < 0 || key >= 3) return;
poll->key[key].fun = fun;
poll->key[key].ud = ud;
}
prev | home | next