I would like to receive only EV_KEY
events with codes 224
and 225
when reading from a /dev/input/event*
file. How do I do that?
As far as I can tell, I need to run ioctl(fd, EVIOCSMASK, &mask)
, but I don't understand how to set up a struct input_mask
with my specifications.
I tried setting type
to EV_KEY
, but that seems to filter out EV_KEY
, and if I set anything in codes_*
(such as an array of codes and a pointer to it), then ioctl
returns -1
.
Look at include/linux/input.h:
The event mask is a per-client mask that specifies which events are forwarded to the client. Each event code is represented by a single bit in the event mask. If the bit is set, the event is passed to the client normally.
In other words:
#include <stdlib.h>
#include <limits.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <errno.h>
#define ULONG_BITS (CHAR_BIT * sizeof (unsigned long))
static void set_bit(unsigned long bits[], size_t bit)
{
bits[bit / ULONG_BITS] |= 1UL << (bit % ULONG_BITS);
}
static void set_keymask(int fd)
{
unsigned long bits[(KEY_CNT + ULONG_BITS - 1) / ULONG_BITS] = { 0 };
struct input_mask mask;
mask.type = EV_KEY;
mask.codes_size = KEY_CNT;
mask.codes_ptr = &bits;
/* Only report KEY_BRIGHTNESSDOWN and KEY_BRIGHTNESSUP */
set_bit(bits, KEY_BRIGHTNESSDOWN);
set_bit(bits, KEY_BRIGHTNESSUP);
if (ioctl(fd, EVIOSMASK, &mask))
return errno;
return 0;
}