hid_mouse.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2022 Benjamin Tissoires
  3. *
  4. * This is a pure HID-BPF example, and should be considered as such:
  5. * on the Etekcity Scroll 6E, the X and Y axes will be swapped and
  6. * inverted. On any other device... Not sure what this will do.
  7. *
  8. * This C main file is generic though. To adapt the code and test, users
  9. * must amend only the .bpf.c file, which this program will load any
  10. * eBPF program it finds.
  11. */
  12. #include <assert.h>
  13. #include <errno.h>
  14. #include <fcntl.h>
  15. #include <libgen.h>
  16. #include <signal.h>
  17. #include <stdbool.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <sys/resource.h>
  22. #include <unistd.h>
  23. #include <linux/bpf.h>
  24. #include <linux/errno.h>
  25. #include <bpf/bpf.h>
  26. #include <bpf/libbpf.h>
  27. #include "hid_mouse.skel.h"
  28. static bool running = true;
  29. static void int_exit(int sig)
  30. {
  31. running = false;
  32. exit(0);
  33. }
  34. static void usage(const char *prog)
  35. {
  36. fprintf(stderr,
  37. "%s: %s /sys/bus/hid/devices/0BUS:0VID:0PID:00ID\n\n",
  38. __func__, prog);
  39. fprintf(stderr,
  40. "This program will upload and attach a HID-BPF program to the given device.\n"
  41. "On the Etekcity Scroll 6E, the X and Y axis will be inverted, but on any other\n"
  42. "device, chances are high that the device will not be working anymore\n\n"
  43. "consider this as a demo and adapt the eBPF program to your needs\n"
  44. "Hit Ctrl-C to unbind the program and reset the device\n");
  45. }
  46. static int get_hid_id(const char *path)
  47. {
  48. const char *str_id, *dir;
  49. char uevent[1024];
  50. int fd;
  51. memset(uevent, 0, sizeof(uevent));
  52. snprintf(uevent, sizeof(uevent) - 1, "%s/uevent", path);
  53. fd = open(uevent, O_RDONLY | O_NONBLOCK);
  54. if (fd < 0)
  55. return -ENOENT;
  56. close(fd);
  57. dir = basename((char *)path);
  58. str_id = dir + sizeof("0003:0001:0A37.");
  59. return (int)strtol(str_id, NULL, 16);
  60. }
  61. int main(int argc, char **argv)
  62. {
  63. struct hid_mouse *skel;
  64. struct bpf_link *link;
  65. int err;
  66. const char *optstr = "";
  67. const char *sysfs_path;
  68. int opt, hid_id;
  69. while ((opt = getopt(argc, argv, optstr)) != -1) {
  70. switch (opt) {
  71. default:
  72. usage(basename(argv[0]));
  73. return 1;
  74. }
  75. }
  76. if (optind == argc) {
  77. usage(basename(argv[0]));
  78. return 1;
  79. }
  80. sysfs_path = argv[optind];
  81. if (!sysfs_path) {
  82. perror("sysfs");
  83. return 1;
  84. }
  85. skel = hid_mouse__open();
  86. if (!skel) {
  87. fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__);
  88. return -1;
  89. }
  90. hid_id = get_hid_id(sysfs_path);
  91. if (hid_id < 0) {
  92. fprintf(stderr, "can not open HID device: %m\n");
  93. return 1;
  94. }
  95. skel->struct_ops.mouse_invert->hid_id = hid_id;
  96. err = hid_mouse__load(skel);
  97. if (err < 0) {
  98. fprintf(stderr, "can not load HID-BPF program: %m\n");
  99. return 1;
  100. }
  101. link = bpf_map__attach_struct_ops(skel->maps.mouse_invert);
  102. if (!link) {
  103. fprintf(stderr, "can not attach HID-BPF program: %m\n");
  104. return 1;
  105. }
  106. signal(SIGINT, int_exit);
  107. signal(SIGTERM, int_exit);
  108. while (running)
  109. sleep(1);
  110. hid_mouse__destroy(skel);
  111. return 0;
  112. }