diff options
-rw-r--r-- | src/SUMMARY.md | 1 | ||||
-rw-r--r-- | src/linux/README.md | 1 | ||||
-rw-r--r-- | src/linux/input.md | 68 | ||||
-rw-r--r-- | src/linux/src/Makefile | 10 | ||||
-rw-r--r-- | src/linux/src/event.c | 75 |
5 files changed, 155 insertions, 0 deletions
diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 8188df2..9af0e9f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -56,6 +56,7 @@ - [ptrace_scope](./linux/ptrace_scope.md) - [cryptsetup](./linux/cryptsetup.md) - [swap](./linux/swap.md) + - [input](./linux/input.md) - [Network](./network/README.md) - [tcpdump](./network/tcpdump.md) diff --git a/src/linux/README.md b/src/linux/README.md index 00e7e68..0cd68a5 100644 --- a/src/linux/README.md +++ b/src/linux/README.md @@ -5,3 +5,4 @@ - [ptrace_scope](./ptrace_scope.md) - [cryptsetup](./cryptsetup.md) - [swap](./swap.md) +- [input](./input.md) diff --git a/src/linux/input.md b/src/linux/input.md new file mode 100644 index 0000000..8a9771e --- /dev/null +++ b/src/linux/input.md @@ -0,0 +1,68 @@ +# Linux input + +Some notes on using `/dev/input/*` device driver files. + +## mouseX / mice + +These device files are created by the [mousedev] driver. + +- `/dev/input/mouseX` represents the input stream for a *SINGLE* mouse device. +- `/dev/input/mice` represents the merged input stream for *ALL* mouse devices. + +The data stream consists of `3 bytes` per `event`. An event is encoded as `(BTN, X, Y)`. +- `BTN` button pressed +- `X` movement in x-direction `-1 -> left` and `1 -> right` +- `Y` movement in y-direction `-1 -> down` and `1 -> up` + +The raw data stream can be inspected as follows. +```bash +sudo cat /dev/input/mice | od -tx1 -w3 -v +``` + +## eventX + +These device files are created by the [evdev] driver. + +- `/dev/input/eventX` represents the generic input event interface a *SINGLE* input deivece. + +Input events are encoded as given by the `input_event` struct below. Reading +from the `eventX` device file will always yield whole number of input events. +```c +struct input_event { + struct timeval time; + unsigned short type; + unsigned short code; + unsigned int value; +}; +``` + +On most 64bit machines the raw data stream can be inspected as follows. +```bash +sudo cat /dev/input/event4 | od -tx1 -w24 -v +``` + +## Identifyin device files. + +To find out which device file is assigned to which input device the following +file `/proc/bus/input/devices` in the proc filesystem can be consulted. + +This yields entries as follows and shows which `Handlers` are assigned to which +`Name`. +``` +I: Bus=0018 Vendor=04f3 Product=0033 Version=0000 +N: Name="Elan Touchpad" +... +H: Handlers=event15 mouse0 +... +``` + +## Example: Toying with `/dev/input/eventX` + +Once compiled, the example should be run as `sudo ./event /dev/input/eventX`. +```c +{{#include src/event.c:7: }} +``` + +[linux-input]: https://www.kernel.org/doc/Documentation/input/input.txt +[mousedev]: TODO /home/johannst/dev/linux/drivers/input/mousedev.c +[evdev]: TODO /home/johannst/dev/linux/drivers/input/evdev.c diff --git a/src/linux/src/Makefile b/src/linux/src/Makefile new file mode 100644 index 0000000..9b6e47a --- /dev/null +++ b/src/linux/src/Makefile @@ -0,0 +1,10 @@ +SRC = event.c +BIN = $(SRC:.c=) + +all: $(BIN) + +%: %.c + bash $< + +clean: + $(RM) $(BIN) diff --git a/src/linux/src/event.c b/src/linux/src/event.c new file mode 100644 index 0000000..d047416 --- /dev/null +++ b/src/linux/src/event.c @@ -0,0 +1,75 @@ +#if NODEF +gcc -o event event.c -Wall -Wextra -Werror -g +exit 0 +#endif +// Copyright (C) 2022 johannst + +#include <stdio.h> +#include <fcntl.h> +#include <assert.h> +#include <unistd.h> +#include <time.h> + +#include <sys/time.h> +#include <linux/input-event-codes.h> + +struct input_event { + struct timeval time; + unsigned short type; + unsigned short code; + unsigned int value; +}; + +const char* type(unsigned short t) { + static char buf[32]; + const char* fmt = "0x%x"; + switch (t) { +#define FMT(TYPE) case TYPE: fmt = #TYPE"(0x%x)"; break + FMT(EV_SYN); + FMT(EV_KEY); + FMT(EV_REL); + FMT(EV_ABS); +#undef FMT + } + snprintf(buf, sizeof(buf), fmt, t); + return buf; +} + +const char* code(unsigned short c) { + static char buf[32]; + const char* fmt = "0x%x"; + switch (c) { +#define FMT(CODE) case CODE: fmt = #CODE"(0x%x)"; break + FMT(BTN_LEFT); + FMT(BTN_RIGHT); + FMT(BTN_MIDDLE); + FMT(REL_X); + FMT(REL_Y); +#undef FMT + } + snprintf(buf, sizeof(buf), fmt, c); + return buf; +} + +const char* timefmt(const struct timeval* t) { + assert(t); + struct tm* lt = localtime(&t->tv_sec); // Returns pointer to static tm object. + static char buf[64]; + strftime(buf, sizeof(buf), "%H:%M:%S", lt); + return buf; +} + +int main(int argc, char* argv[]) { + assert(argc == 2); + + int fd = open(argv[1], O_RDONLY); + assert(fd != -1); + + struct input_event inp; + while (1) { + int ret = read(fd, &inp, sizeof(inp)); + assert(ret == sizeof(inp)); + printf("time: %s type: %s code: %s value: 0x%x\n", + timefmt(&inp.time), type(inp.type), code(inp.code), inp.value); + } +} |