An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
124 lines
3.2 KiB
C
124 lines
3.2 KiB
C
// inputtest -- read raw events from /dev/input/eventN.
|
|
//
|
|
// The point of the raw devices is everything the console cannot say: which
|
|
// key was released, whether one is still held, and where the mouse went. None
|
|
// of that shows up in a character stream, so none of it can be tested by
|
|
// typing into a shell.
|
|
//
|
|
// inputtest read the keyboard until Esc is released
|
|
// inputtest mouse read the mouse until interrupted
|
|
// inputtest -n N stop after N events (used by the boot check)
|
|
//
|
|
// Prints one line per event: type, code and value, decoded where there is a
|
|
// name for it.
|
|
|
|
#include "types.h"
|
|
#include "user.h"
|
|
#include "fcntl.h"
|
|
#include "input.h"
|
|
|
|
static void
|
|
puts_(const char *s)
|
|
{
|
|
int n = 0;
|
|
while (s[n]) n++;
|
|
write(1, (void*)s, n);
|
|
}
|
|
|
|
static void
|
|
putn_(int v)
|
|
{
|
|
char buf[12];
|
|
int i = 0, neg = 0;
|
|
if (v < 0) { neg = 1; v = -v; }
|
|
if (v == 0) buf[i++] = '0';
|
|
while (v) { buf[i++] = '0' + (v % 10); v /= 10; }
|
|
if (neg) buf[i++] = '-';
|
|
while (i--) write(1, &buf[i], 1);
|
|
}
|
|
|
|
static const char *
|
|
typename_(int t)
|
|
{
|
|
switch (t) {
|
|
case EV_SYN: return "SYN";
|
|
case EV_KEY: return "KEY";
|
|
case EV_REL: return "REL";
|
|
default: return "?";
|
|
}
|
|
}
|
|
|
|
static int
|
|
streq(const char *a, const char *b)
|
|
{
|
|
while (*a && *a == *b) { a++; b++; }
|
|
return *a == *b;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
const char *path = "/dev/input/event0";
|
|
int limit = 0, count = 0, i;
|
|
int fd;
|
|
struct input_event ev;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
if (streq(argv[i], "mouse"))
|
|
path = "/dev/input/event1";
|
|
else if (streq(argv[i], "-n") && i + 1 < argc) {
|
|
const char *p = argv[++i];
|
|
limit = 0;
|
|
while (*p >= '0' && *p <= '9') limit = limit * 10 + (*p++ - '0');
|
|
}
|
|
}
|
|
|
|
fd = open((char*)path, O_RDONLY);
|
|
if (fd < 0) {
|
|
puts_("inputtest: cannot open ");
|
|
puts_(path);
|
|
puts_("\n");
|
|
exit();
|
|
}
|
|
puts_("inputtest: reading ");
|
|
puts_(path);
|
|
puts_("\n");
|
|
|
|
for (;;) {
|
|
int n = read(fd, &ev, sizeof(ev));
|
|
|
|
// A short read would mean the device handed back part of a struct,
|
|
// which would desynchronise every event after it. Saying so is more
|
|
// use than silently carrying on with garbage.
|
|
if (n == 0) { puts_("inputtest: end of stream\n"); break; }
|
|
if (n < 0) { puts_("inputtest: read error\n"); break; }
|
|
if (n != sizeof(ev)) {
|
|
puts_("inputtest: SHORT READ -- events are not whole\n");
|
|
break;
|
|
}
|
|
|
|
puts_(" ");
|
|
puts_(typename_(ev.type));
|
|
puts_(" code ");
|
|
putn_(ev.code);
|
|
puts_(" value ");
|
|
putn_(ev.value);
|
|
if (ev.type == EV_KEY)
|
|
puts_(ev.value ? " (press)" : " (release)");
|
|
puts_("\n");
|
|
|
|
// Esc released ends the keyboard run, so a person can stop it without
|
|
// a signal. The boot check uses -n instead.
|
|
if (ev.type == EV_KEY && ev.code == KEY_ESC && ev.value == 0)
|
|
break;
|
|
|
|
if (limit && ++count >= limit) {
|
|
puts_("inputtest: event limit reached\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
puts_("inputtest: done\n");
|
|
exit();
|
|
}
|