Merge tag 'ubifs-for-linus-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / samples / hid / hid_mouse.c
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
13 #include <assert.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <libgen.h>
17 #include <signal.h>
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/resource.h>
23 #include <unistd.h>
24
25 #include <linux/bpf.h>
26 #include <linux/errno.h>
27
28 #include <bpf/bpf.h>
29 #include <bpf/libbpf.h>
30
31 #include "hid_mouse.skel.h"
32 #include "hid_bpf_attach.h"
33
34 static bool running = true;
35
36 static void int_exit(int sig)
37 {
38         running = false;
39         exit(0);
40 }
41
42 static void usage(const char *prog)
43 {
44         fprintf(stderr,
45                 "%s: %s /sys/bus/hid/devices/0BUS:0VID:0PID:00ID\n\n",
46                 __func__, prog);
47         fprintf(stderr,
48                 "This program will upload and attach a HID-BPF program to the given device.\n"
49                 "On the Etekcity Scroll 6E, the X and Y axis will be inverted, but on any other\n"
50                 "device, chances are high that the device will not be working anymore\n\n"
51                 "consider this as a demo and adapt the eBPF program to your needs\n"
52                 "Hit Ctrl-C to unbind the program and reset the device\n");
53 }
54
55 static int get_hid_id(const char *path)
56 {
57         const char *str_id, *dir;
58         char uevent[1024];
59         int fd;
60
61         memset(uevent, 0, sizeof(uevent));
62         snprintf(uevent, sizeof(uevent) - 1, "%s/uevent", path);
63
64         fd = open(uevent, O_RDONLY | O_NONBLOCK);
65         if (fd < 0)
66                 return -ENOENT;
67
68         close(fd);
69
70         dir = basename((char *)path);
71
72         str_id = dir + sizeof("0003:0001:0A37.");
73         return (int)strtol(str_id, NULL, 16);
74 }
75
76 int main(int argc, char **argv)
77 {
78         struct hid_mouse *skel;
79         struct bpf_program *prog;
80         int err;
81         const char *optstr = "";
82         const char *sysfs_path;
83         int opt, hid_id, attach_fd;
84         struct attach_prog_args args = {
85                 .retval = -1,
86         };
87         DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
88                             .ctx_in = &args,
89                             .ctx_size_in = sizeof(args),
90         );
91
92         while ((opt = getopt(argc, argv, optstr)) != -1) {
93                 switch (opt) {
94                 default:
95                         usage(basename(argv[0]));
96                         return 1;
97                 }
98         }
99
100         if (optind == argc) {
101                 usage(basename(argv[0]));
102                 return 1;
103         }
104
105         sysfs_path = argv[optind];
106         if (!sysfs_path) {
107                 perror("sysfs");
108                 return 1;
109         }
110
111         skel = hid_mouse__open_and_load();
112         if (!skel) {
113                 fprintf(stderr, "%s  %s:%d", __func__, __FILE__, __LINE__);
114                 return -1;
115         }
116
117         hid_id = get_hid_id(sysfs_path);
118
119         if (hid_id < 0) {
120                 fprintf(stderr, "can not open HID device: %m\n");
121                 return 1;
122         }
123         args.hid = hid_id;
124
125         attach_fd = bpf_program__fd(skel->progs.attach_prog);
126         if (attach_fd < 0) {
127                 fprintf(stderr, "can't locate attach prog: %m\n");
128                 return 1;
129         }
130
131         bpf_object__for_each_program(prog, *skel->skeleton->obj) {
132                 /* ignore syscalls */
133                 if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING)
134                         continue;
135
136                 args.retval = -1;
137                 args.prog_fd = bpf_program__fd(prog);
138                 err = bpf_prog_test_run_opts(attach_fd, &tattr);
139                 if (err) {
140                         fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n",
141                                 hid_id, err);
142                         return 1;
143                 }
144         }
145
146         signal(SIGINT, int_exit);
147         signal(SIGTERM, int_exit);
148
149         while (running)
150                 sleep(1);
151
152         hid_mouse__destroy(skel);
153
154         return 0;
155 }