2020/7/31

Bookmarks : reading input device

5. Event interface
~~~~~~~~~~~~~~~~~~
  Should you want to add event device support into any application (X, gpm,
svgalib ...) I >vojtech@ucw.cz< will be happy to provide you any help I
can. Here goes a description of the current state of things, which is going
to be extended, but not changed incompatibly as time goes:

  You can use blocking and nonblocking reads, also select() on the
/dev/input/eventX devices, and you'll always get a whole number of input
events on a read. Their layout is:

struct input_event {
	struct timeval time;
	unsigned short type;
	unsigned short code;
	unsigned int value;
};

  'time' is the timestamp, it returns the time at which the event happened.
Type is for example EV_REL for relative moment, EV_KEY for a keypress or
release. More types are defined in include/uapi/linux/input-event-codes.h.

  'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/uapi/linux/input-event-codes.h.

  'value' is the value the event carries. Either a relative change for
EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
release, 1 for keypress and 2 for autorepeat.
所以對/dev/input/eventX 讀取,會得到的資料內容是 input_event structure


上面ref link 的 example (keymonitor.c) :

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>


static const char * const evval[]={
	"RELEASED",
	"PRESSED",
	"REPEATED"
};

int main(void)
{
	const char *dev="/dev/input/by-path/platform-i8042-serio-0-event-kbd";
	struct input_event ev;
	ssize_t n;
	int fd;

	fd = open(dev, O_RDONLY);
	if (fd==-1) {
		fprintf(stderr,"Cannot open %s: %s\n",dev,strerror(errno));
		return EXIT_FAILURE;
	}

	while(1) {
		n = read(fd, &ev, sizeof(ev));
		if (n == (ssize_t)-1) {
			if (errno==EINTR)
				continue;
			else
				break;
		}else
		if (n != sizeof(ev)) {
			errno = EIO;
			break;
		}

		if(ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
			printf("%s 0x%04x (%d)\n",evval[ev.value],(int)ev.code,(int)ev.code);

	}
	fflush(stdout);
	fprintf(stderr,"%s.\n",strerror(errno));
	return EXIT_FAILURE;
}

要注意 /dev/input/by-path/platform-i8042-serio-0-event-kbd 的權限。
link 到 event3,event 的權限 是 input group。
所以要把user 加入 input group

實際執行:

:~/test/input$ ./keymonitor 
RELEASED 0x001c (28)
PRESSED 0x0002 (2)
1RELEASED 0x0002 (2)
PRESSED 0x0003 (3)
2RELEASED 0x0003 (3)
PRESSED 0x0004 (4)
3RELEASED 0x0004 (4)
PRESSED 0x0005 (5)
4RELEASED 0x0005 (5)
PRESSED 0x0006 (6)
5RELEASED 0x0006 (6)
PRESSED 0x001e (30)
aRELEASED 0x001e (30)
PRESSED 0x0030 (48)
bRELEASED 0x0030 (48)
PRESSED 0x002e (46)
cRELEASED 0x002e (46)
PRESSED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
REPEATED 0x001d (29)
PRESSED 0x002e (46)
^C

即使不在console 不在 focus,也會擷取到keyboard input.
... 有點像 keylogger...

沒有留言:

張貼留言