// SPDX-License-Identifier: GPL-2.0-only /* * Userspace replacement for mac_hid.c from Linux. * * Copyright (C) 2022 Thomas Weißschuh */ /* cc $(pkg-config --cflags libevdev) $(pkg-config --libs libevdev) mac_hid_userspace.c -o mac_hid_userspace */ #define _GNU_SOURCE #include #include #include #include #include #include #include static void update_name(struct libevdev *dev) { char *name; int rc = asprintf(&name, "%s (mac_hid)", libevdev_get_name(dev)); assert(rc > 0); libevdev_set_name(dev, name); free(name); } int main(int argc, char **argv) { int button2 = KEY_RIGHTCTRL; int button3 = KEY_RIGHTALT; if (argc != 2 && argc != 4) { fprintf(stderr, "usage: %s DEVICE [BUTTON2 BUTTON3]\n", argv[0]); return 1; } if (argc == 4) { char *endptr; button2 = strtol(argv[2], &endptr, 0); assert(!*endptr); button3 = strtol(argv[3], &endptr, 0); assert(!*endptr); } struct libevdev *dev; int fd = open(argv[1], O_RDONLY); assert(fd != -1); int rc = libevdev_new_from_fd(fd, &dev); assert(rc == 0); libevdev_enable_event_type(dev, EV_KEY); libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE, NULL); libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT, NULL); update_name(dev); struct libevdev_uinput *uinput_dev; rc = libevdev_uinput_create_from_device( dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &uinput_dev); assert(rc == 0); rc = libevdev_grab(dev, LIBEVDEV_GRAB); assert(rc == 0); while (1) { struct input_event ev; rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev); assert(rc == 0); if (ev.type == EV_KEY) { if (ev.code == button2) ev.code = BTN_MIDDLE; else if (ev.code == button3) ev.code = BTN_RIGHT; } rc = libevdev_uinput_write_event(uinput_dev, ev.type, ev.code, ev.value); assert(rc == 0); } libevdev_uinput_destroy(uinput_dev); libevdev_free(dev); }