drm/panel: panel-himax-hx83102: support for csot-pna957qt1-1 MIPI-DSI panel
[drm/drm-misc.git] / tools / testing / selftests / hid / hid_bpf.c
blob1e979fb3542bab79803ae2c772e048d93927df33
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022-2024 Red Hat */
3 #include "hid.skel.h"
4 #include "hid_common.h"
5 #include <bpf/bpf.h>
7 struct hid_hw_request_syscall_args {
8 __u8 data[10];
9 unsigned int hid;
10 int retval;
11 size_t size;
12 enum hid_report_type type;
13 __u8 request_type;
16 FIXTURE(hid_bpf) {
17 struct uhid_device hid;
18 int hidraw_fd;
19 struct hid *skel;
20 struct bpf_link *hid_links[3]; /* max number of programs loaded in a single test */
22 static void detach_bpf(FIXTURE_DATA(hid_bpf) * self)
24 int i;
26 if (self->hidraw_fd)
27 close(self->hidraw_fd);
28 self->hidraw_fd = 0;
30 if (!self->skel)
31 return;
33 hid__detach(self->skel);
35 for (i = 0; i < ARRAY_SIZE(self->hid_links); i++) {
36 if (self->hid_links[i])
37 bpf_link__destroy(self->hid_links[i]);
40 hid__destroy(self->skel);
41 self->skel = NULL;
44 FIXTURE_TEARDOWN(hid_bpf) {
45 void *uhid_err;
47 uhid_destroy(_metadata, &self->hid);
49 detach_bpf(self);
50 pthread_join(self->hid.tid, &uhid_err);
52 #define TEARDOWN_LOG(fmt, ...) do { \
53 TH_LOG(fmt, ##__VA_ARGS__); \
54 hid_bpf_teardown(_metadata, self, variant); \
55 } while (0)
57 FIXTURE_SETUP(hid_bpf)
59 int err;
61 err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a36, rdesc, sizeof(rdesc));
62 ASSERT_OK(err);
65 struct test_program {
66 const char *name;
67 int insert_head;
69 #define LOAD_PROGRAMS(progs) \
70 load_programs(progs, ARRAY_SIZE(progs), _metadata, self, variant)
71 #define LOAD_BPF \
72 load_programs(NULL, 0, _metadata, self, variant)
73 static void load_programs(const struct test_program programs[],
74 const size_t progs_count,
75 struct __test_metadata *_metadata,
76 FIXTURE_DATA(hid_bpf) * self,
77 const FIXTURE_VARIANT(hid_bpf) * variant)
79 struct bpf_map *iter_map;
80 int err = -EINVAL;
82 ASSERT_LE(progs_count, ARRAY_SIZE(self->hid_links))
83 TH_LOG("too many programs are to be loaded");
85 /* open the bpf file */
86 self->skel = hid__open();
87 ASSERT_OK_PTR(self->skel) TEARDOWN_LOG("Error while calling hid__open");
89 for (int i = 0; i < progs_count; i++) {
90 struct bpf_program *prog;
91 struct bpf_map *map;
92 int *ops_hid_id;
94 prog = bpf_object__find_program_by_name(*self->skel->skeleton->obj,
95 programs[i].name);
96 ASSERT_OK_PTR(prog) TH_LOG("can not find program by name '%s'", programs[i].name);
98 bpf_program__set_autoload(prog, true);
100 map = bpf_object__find_map_by_name(*self->skel->skeleton->obj,
101 programs[i].name + 4);
102 ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'",
103 programs[i].name + 4);
105 /* hid_id is the first field of struct hid_bpf_ops */
106 ops_hid_id = bpf_map__initial_value(map, NULL);
107 ASSERT_OK_PTR(ops_hid_id) TH_LOG("unable to retrieve struct_ops data");
109 *ops_hid_id = self->hid.hid_id;
112 /* we disable the auto-attach feature of all maps because we
113 * only want the tested one to be manually attached in the next
114 * call to bpf_map__attach_struct_ops()
116 bpf_object__for_each_map(iter_map, *self->skel->skeleton->obj)
117 bpf_map__set_autoattach(iter_map, false);
119 err = hid__load(self->skel);
120 ASSERT_OK(err) TH_LOG("hid_skel_load failed: %d", err);
122 for (int i = 0; i < progs_count; i++) {
123 struct bpf_map *map;
125 map = bpf_object__find_map_by_name(*self->skel->skeleton->obj,
126 programs[i].name + 4);
127 ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'",
128 programs[i].name + 4);
130 self->hid_links[i] = bpf_map__attach_struct_ops(map);
131 ASSERT_OK_PTR(self->hid_links[i]) TH_LOG("failed to attach struct ops '%s'",
132 programs[i].name + 4);
135 hid__attach(self->skel);
137 self->hidraw_fd = open_hidraw(&self->hid);
138 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
142 * A simple test to see if the fixture is working fine.
143 * If this fails, none of the other tests will pass.
145 TEST_F(hid_bpf, test_create_uhid)
150 * Attach hid_first_event to the given uhid device,
151 * retrieve and open the matching hidraw node,
152 * inject one event in the uhid device,
153 * check that the program sees it and can change the data
155 TEST_F(hid_bpf, raw_event)
157 const struct test_program progs[] = {
158 { .name = "hid_first_event" },
160 __u8 buf[10] = {0};
161 int err;
163 LOAD_PROGRAMS(progs);
165 /* check that the program is correctly loaded */
166 ASSERT_EQ(self->skel->data->callback_check, 52) TH_LOG("callback_check1");
167 ASSERT_EQ(self->skel->data->callback2_check, 52) TH_LOG("callback2_check1");
169 /* inject one event */
170 buf[0] = 1;
171 buf[1] = 42;
172 uhid_send_event(_metadata, &self->hid, buf, 6);
174 /* check that hid_first_event() was executed */
175 ASSERT_EQ(self->skel->data->callback_check, 42) TH_LOG("callback_check1");
177 /* read the data from hidraw */
178 memset(buf, 0, sizeof(buf));
179 err = read(self->hidraw_fd, buf, sizeof(buf));
180 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
181 ASSERT_EQ(buf[0], 1);
182 ASSERT_EQ(buf[2], 47);
184 /* inject another event */
185 memset(buf, 0, sizeof(buf));
186 buf[0] = 1;
187 buf[1] = 47;
188 uhid_send_event(_metadata, &self->hid, buf, 6);
190 /* check that hid_first_event() was executed */
191 ASSERT_EQ(self->skel->data->callback_check, 47) TH_LOG("callback_check1");
193 /* read the data from hidraw */
194 memset(buf, 0, sizeof(buf));
195 err = read(self->hidraw_fd, buf, sizeof(buf));
196 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
197 ASSERT_EQ(buf[2], 52);
201 * Attach hid_first_event to the given uhid device,
202 * retrieve and open the matching hidraw node,
203 * inject one event in the uhid device,
204 * check that the program sees it and can change the data
206 TEST_F(hid_bpf, subprog_raw_event)
208 const struct test_program progs[] = {
209 { .name = "hid_subprog_first_event" },
211 __u8 buf[10] = {0};
212 int err;
214 LOAD_PROGRAMS(progs);
216 /* inject one event */
217 buf[0] = 1;
218 buf[1] = 42;
219 uhid_send_event(_metadata, &self->hid, buf, 6);
221 /* read the data from hidraw */
222 memset(buf, 0, sizeof(buf));
223 err = read(self->hidraw_fd, buf, sizeof(buf));
224 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
225 ASSERT_EQ(buf[0], 1);
226 ASSERT_EQ(buf[2], 47);
228 /* inject another event */
229 memset(buf, 0, sizeof(buf));
230 buf[0] = 1;
231 buf[1] = 47;
232 uhid_send_event(_metadata, &self->hid, buf, 6);
234 /* read the data from hidraw */
235 memset(buf, 0, sizeof(buf));
236 err = read(self->hidraw_fd, buf, sizeof(buf));
237 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
238 ASSERT_EQ(buf[2], 52);
242 * Attach hid_first_event to the given uhid device,
243 * attempt at re-attaching it, we should not lock and
244 * return an invalid struct bpf_link
246 TEST_F(hid_bpf, multiple_attach)
248 const struct test_program progs[] = {
249 { .name = "hid_first_event" },
251 struct bpf_link *link;
253 LOAD_PROGRAMS(progs);
255 link = bpf_map__attach_struct_ops(self->skel->maps.first_event);
256 ASSERT_NULL(link) TH_LOG("unexpected return value when re-attaching the struct_ops");
260 * Ensures that we can attach/detach programs
262 TEST_F(hid_bpf, test_attach_detach)
264 const struct test_program progs[] = {
265 { .name = "hid_first_event" },
266 { .name = "hid_second_event" },
268 struct bpf_link *link;
269 __u8 buf[10] = {0};
270 int err, link_fd;
272 LOAD_PROGRAMS(progs);
274 link = self->hid_links[0];
275 ASSERT_OK_PTR(link) TH_LOG("HID-BPF link not created");
277 link_fd = bpf_link__fd(link);
278 ASSERT_GE(link_fd, 0) TH_LOG("HID-BPF link FD not valid");
280 /* inject one event */
281 buf[0] = 1;
282 buf[1] = 42;
283 uhid_send_event(_metadata, &self->hid, buf, 6);
285 /* read the data from hidraw */
286 memset(buf, 0, sizeof(buf));
287 err = read(self->hidraw_fd, buf, sizeof(buf));
288 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
289 ASSERT_EQ(buf[0], 1);
290 ASSERT_EQ(buf[2], 47);
292 /* make sure both programs are run */
293 ASSERT_EQ(buf[3], 52);
295 /* pin the first program and immediately unpin it */
296 #define PIN_PATH "/sys/fs/bpf/hid_first_event"
297 err = bpf_obj_pin(link_fd, PIN_PATH);
298 ASSERT_OK(err) TH_LOG("error while calling bpf_obj_pin");
299 remove(PIN_PATH);
300 #undef PIN_PATH
301 usleep(100000);
303 /* detach the program */
304 detach_bpf(self);
306 self->hidraw_fd = open_hidraw(&self->hid);
307 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
309 /* inject another event */
310 memset(buf, 0, sizeof(buf));
311 buf[0] = 1;
312 buf[1] = 47;
313 uhid_send_event(_metadata, &self->hid, buf, 6);
315 /* read the data from hidraw */
316 memset(buf, 0, sizeof(buf));
317 err = read(self->hidraw_fd, buf, sizeof(buf));
318 ASSERT_EQ(err, 6) TH_LOG("read_hidraw_no_bpf");
319 ASSERT_EQ(buf[0], 1);
320 ASSERT_EQ(buf[1], 47);
321 ASSERT_EQ(buf[2], 0);
322 ASSERT_EQ(buf[3], 0);
324 /* re-attach our program */
326 LOAD_PROGRAMS(progs);
328 /* inject one event */
329 memset(buf, 0, sizeof(buf));
330 buf[0] = 1;
331 buf[1] = 42;
332 uhid_send_event(_metadata, &self->hid, buf, 6);
334 /* read the data from hidraw */
335 memset(buf, 0, sizeof(buf));
336 err = read(self->hidraw_fd, buf, sizeof(buf));
337 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
338 ASSERT_EQ(buf[0], 1);
339 ASSERT_EQ(buf[2], 47);
340 ASSERT_EQ(buf[3], 52);
344 * Attach hid_change_report_id to the given uhid device,
345 * retrieve and open the matching hidraw node,
346 * inject one event in the uhid device,
347 * check that the program sees it and can change the data
349 TEST_F(hid_bpf, test_hid_change_report)
351 const struct test_program progs[] = {
352 { .name = "hid_change_report_id" },
354 __u8 buf[10] = {0};
355 int err;
357 LOAD_PROGRAMS(progs);
359 /* inject one event */
360 buf[0] = 1;
361 buf[1] = 42;
362 uhid_send_event(_metadata, &self->hid, buf, 6);
364 /* read the data from hidraw */
365 memset(buf, 0, sizeof(buf));
366 err = read(self->hidraw_fd, buf, sizeof(buf));
367 ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
368 ASSERT_EQ(buf[0], 2);
369 ASSERT_EQ(buf[1], 42);
370 ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test");
374 * Call hid_bpf_input_report against the given uhid device,
375 * check that the program is called and does the expected.
377 TEST_F(hid_bpf, test_hid_user_input_report_call)
379 struct hid_hw_request_syscall_args args = {
380 .retval = -1,
381 .size = 10,
383 DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
384 .ctx_in = &args,
385 .ctx_size_in = sizeof(args),
387 __u8 buf[10] = {0};
388 int err, prog_fd;
390 LOAD_BPF;
392 args.hid = self->hid.hid_id;
393 args.data[0] = 1; /* report ID */
394 args.data[1] = 2; /* report ID */
395 args.data[2] = 42; /* report ID */
397 prog_fd = bpf_program__fd(self->skel->progs.hid_user_input_report);
399 /* check that there is no data to read from hidraw */
400 memset(buf, 0, sizeof(buf));
401 err = read(self->hidraw_fd, buf, sizeof(buf));
402 ASSERT_EQ(err, -1) TH_LOG("read_hidraw");
404 err = bpf_prog_test_run_opts(prog_fd, &tattrs);
406 ASSERT_OK(err) TH_LOG("error while calling bpf_prog_test_run_opts");
408 ASSERT_EQ(args.retval, 0);
410 /* read the data from hidraw */
411 memset(buf, 0, sizeof(buf));
412 err = read(self->hidraw_fd, buf, sizeof(buf));
413 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
414 ASSERT_EQ(buf[0], 1);
415 ASSERT_EQ(buf[1], 2);
416 ASSERT_EQ(buf[2], 42);
420 * Call hid_bpf_hw_output_report against the given uhid device,
421 * check that the program is called and does the expected.
423 TEST_F(hid_bpf, test_hid_user_output_report_call)
425 struct hid_hw_request_syscall_args args = {
426 .retval = -1,
427 .size = 10,
429 DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
430 .ctx_in = &args,
431 .ctx_size_in = sizeof(args),
433 int err, cond_err, prog_fd;
434 struct timespec time_to_wait;
436 LOAD_BPF;
438 args.hid = self->hid.hid_id;
439 args.data[0] = 1; /* report ID */
440 args.data[1] = 2; /* report ID */
441 args.data[2] = 42; /* report ID */
443 prog_fd = bpf_program__fd(self->skel->progs.hid_user_output_report);
445 pthread_mutex_lock(&uhid_output_mtx);
447 memset(output_report, 0, sizeof(output_report));
448 clock_gettime(CLOCK_REALTIME, &time_to_wait);
449 time_to_wait.tv_sec += 2;
451 err = bpf_prog_test_run_opts(prog_fd, &tattrs);
452 cond_err = pthread_cond_timedwait(&uhid_output_cond, &uhid_output_mtx, &time_to_wait);
454 ASSERT_OK(err) TH_LOG("error while calling bpf_prog_test_run_opts");
455 ASSERT_OK(cond_err) TH_LOG("error while calling waiting for the condition");
457 ASSERT_EQ(args.retval, 3);
459 ASSERT_EQ(output_report[0], 1);
460 ASSERT_EQ(output_report[1], 2);
461 ASSERT_EQ(output_report[2], 42);
463 pthread_mutex_unlock(&uhid_output_mtx);
467 * Call hid_hw_raw_request against the given uhid device,
468 * check that the program is called and does the expected.
470 TEST_F(hid_bpf, test_hid_user_raw_request_call)
472 struct hid_hw_request_syscall_args args = {
473 .retval = -1,
474 .type = HID_FEATURE_REPORT,
475 .request_type = HID_REQ_GET_REPORT,
476 .size = 10,
478 DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
479 .ctx_in = &args,
480 .ctx_size_in = sizeof(args),
482 int err, prog_fd;
484 LOAD_BPF;
486 args.hid = self->hid.hid_id;
487 args.data[0] = 1; /* report ID */
489 prog_fd = bpf_program__fd(self->skel->progs.hid_user_raw_request);
491 err = bpf_prog_test_run_opts(prog_fd, &tattrs);
492 ASSERT_OK(err) TH_LOG("error while calling bpf_prog_test_run_opts");
494 ASSERT_EQ(args.retval, 2);
496 ASSERT_EQ(args.data[1], 2);
500 * Call hid_hw_raw_request against the given uhid device,
501 * check that the program is called and prevents the
502 * call to uhid.
504 TEST_F(hid_bpf, test_hid_filter_raw_request_call)
506 const struct test_program progs[] = {
507 { .name = "hid_test_filter_raw_request" },
509 __u8 buf[10] = {0};
510 int err;
512 LOAD_PROGRAMS(progs);
514 /* first check that we did not attach to device_event */
516 /* inject one event */
517 buf[0] = 1;
518 buf[1] = 42;
519 uhid_send_event(_metadata, &self->hid, buf, 6);
521 /* read the data from hidraw */
522 memset(buf, 0, sizeof(buf));
523 err = read(self->hidraw_fd, buf, sizeof(buf));
524 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
525 ASSERT_EQ(buf[0], 1);
526 ASSERT_EQ(buf[1], 42);
527 ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test");
529 /* now check that our program is preventing hid_hw_raw_request() */
531 /* emit hid_hw_raw_request from hidraw */
532 /* Get Feature */
533 memset(buf, 0, sizeof(buf));
534 buf[0] = 0x1; /* Report Number */
535 err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
536 ASSERT_LT(err, 0) TH_LOG("unexpected success while reading HIDIOCGFEATURE: %d", err);
537 ASSERT_EQ(errno, 20) TH_LOG("unexpected error code while reading HIDIOCGFEATURE: %d",
538 errno);
540 /* remove our bpf program and check that we can now emit commands */
542 /* detach the program */
543 detach_bpf(self);
545 self->hidraw_fd = open_hidraw(&self->hid);
546 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
548 err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
549 ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGFEATURE: %d", err);
553 * Call hid_hw_raw_request against the given uhid device,
554 * check that the program is called and can issue the call
555 * to uhid and transform the answer.
557 TEST_F(hid_bpf, test_hid_change_raw_request_call)
559 const struct test_program progs[] = {
560 { .name = "hid_test_hidraw_raw_request" },
562 __u8 buf[10] = {0};
563 int err;
565 LOAD_PROGRAMS(progs);
567 /* emit hid_hw_raw_request from hidraw */
568 /* Get Feature */
569 memset(buf, 0, sizeof(buf));
570 buf[0] = 0x1; /* Report Number */
571 err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
572 ASSERT_EQ(err, 3) TH_LOG("unexpected returned size while reading HIDIOCGFEATURE: %d", err);
574 ASSERT_EQ(buf[0], 2);
575 ASSERT_EQ(buf[1], 3);
576 ASSERT_EQ(buf[2], 4);
580 * Call hid_hw_raw_request against the given uhid device,
581 * check that the program is not making infinite loops.
583 TEST_F(hid_bpf, test_hid_infinite_loop_raw_request_call)
585 const struct test_program progs[] = {
586 { .name = "hid_test_infinite_loop_raw_request" },
588 __u8 buf[10] = {0};
589 int err;
591 LOAD_PROGRAMS(progs);
593 /* emit hid_hw_raw_request from hidraw */
594 /* Get Feature */
595 memset(buf, 0, sizeof(buf));
596 buf[0] = 0x1; /* Report Number */
597 err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
598 ASSERT_EQ(err, 3) TH_LOG("unexpected returned size while reading HIDIOCGFEATURE: %d", err);
602 * Call hid_hw_output_report against the given uhid device,
603 * check that the program is called and prevents the
604 * call to uhid.
606 TEST_F(hid_bpf, test_hid_filter_output_report_call)
608 const struct test_program progs[] = {
609 { .name = "hid_test_filter_output_report" },
611 __u8 buf[10] = {0};
612 int err;
614 LOAD_PROGRAMS(progs);
616 /* first check that we did not attach to device_event */
618 /* inject one event */
619 buf[0] = 1;
620 buf[1] = 42;
621 uhid_send_event(_metadata, &self->hid, buf, 6);
623 /* read the data from hidraw */
624 memset(buf, 0, sizeof(buf));
625 err = read(self->hidraw_fd, buf, sizeof(buf));
626 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
627 ASSERT_EQ(buf[0], 1);
628 ASSERT_EQ(buf[1], 42);
629 ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test");
631 /* now check that our program is preventing hid_hw_output_report() */
633 buf[0] = 1; /* report ID */
634 buf[1] = 2;
635 buf[2] = 42;
637 err = write(self->hidraw_fd, buf, 3);
638 ASSERT_LT(err, 0) TH_LOG("unexpected success while sending hid_hw_output_report: %d", err);
639 ASSERT_EQ(errno, 25) TH_LOG("unexpected error code while sending hid_hw_output_report: %d",
640 errno);
642 /* remove our bpf program and check that we can now emit commands */
644 /* detach the program */
645 detach_bpf(self);
647 self->hidraw_fd = open_hidraw(&self->hid);
648 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
650 err = write(self->hidraw_fd, buf, 3);
651 ASSERT_GE(err, 0) TH_LOG("error while sending hid_hw_output_report: %d", err);
655 * Call hid_hw_output_report against the given uhid device,
656 * check that the program is called and can issue the call
657 * to uhid and transform the answer.
659 TEST_F(hid_bpf, test_hid_change_output_report_call)
661 const struct test_program progs[] = {
662 { .name = "hid_test_hidraw_output_report" },
664 __u8 buf[10] = {0};
665 int err;
667 LOAD_PROGRAMS(progs);
669 /* emit hid_hw_output_report from hidraw */
670 buf[0] = 1; /* report ID */
671 buf[1] = 2;
672 buf[2] = 42;
674 err = write(self->hidraw_fd, buf, 10);
675 ASSERT_EQ(err, 2) TH_LOG("unexpected returned size while sending hid_hw_output_report: %d",
676 err);
680 * Call hid_hw_output_report against the given uhid device,
681 * check that the program is not making infinite loops.
683 TEST_F(hid_bpf, test_hid_infinite_loop_output_report_call)
685 const struct test_program progs[] = {
686 { .name = "hid_test_infinite_loop_output_report" },
688 __u8 buf[10] = {0};
689 int err;
691 LOAD_PROGRAMS(progs);
693 /* emit hid_hw_output_report from hidraw */
694 buf[0] = 1; /* report ID */
695 buf[1] = 2;
696 buf[2] = 42;
698 err = write(self->hidraw_fd, buf, 8);
699 ASSERT_EQ(err, 2) TH_LOG("unexpected returned size while sending hid_hw_output_report: %d",
700 err);
704 * Attach hid_multiply_event_wq to the given uhid device,
705 * retrieve and open the matching hidraw node,
706 * inject one event in the uhid device,
707 * check that the program sees it and can add extra data
709 TEST_F(hid_bpf, test_multiply_events_wq)
711 const struct test_program progs[] = {
712 { .name = "hid_test_multiply_events_wq" },
714 __u8 buf[10] = {0};
715 int err;
717 LOAD_PROGRAMS(progs);
719 /* inject one event */
720 buf[0] = 1;
721 buf[1] = 42;
722 uhid_send_event(_metadata, &self->hid, buf, 6);
724 /* read the data from hidraw */
725 memset(buf, 0, sizeof(buf));
726 err = read(self->hidraw_fd, buf, sizeof(buf));
727 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
728 ASSERT_EQ(buf[0], 1);
729 ASSERT_EQ(buf[1], 47);
731 usleep(100000);
733 /* read the data from hidraw */
734 memset(buf, 0, sizeof(buf));
735 err = read(self->hidraw_fd, buf, sizeof(buf));
736 ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
737 ASSERT_EQ(buf[0], 2);
738 ASSERT_EQ(buf[1], 3);
742 * Attach hid_multiply_event to the given uhid device,
743 * retrieve and open the matching hidraw node,
744 * inject one event in the uhid device,
745 * check that the program sees it and can add extra data
747 TEST_F(hid_bpf, test_multiply_events)
749 const struct test_program progs[] = {
750 { .name = "hid_test_multiply_events" },
752 __u8 buf[10] = {0};
753 int err;
755 LOAD_PROGRAMS(progs);
757 /* inject one event */
758 buf[0] = 1;
759 buf[1] = 42;
760 uhid_send_event(_metadata, &self->hid, buf, 6);
762 /* read the data from hidraw */
763 memset(buf, 0, sizeof(buf));
764 err = read(self->hidraw_fd, buf, sizeof(buf));
765 ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
766 ASSERT_EQ(buf[0], 2);
767 ASSERT_EQ(buf[1], 47);
769 /* read the data from hidraw */
770 memset(buf, 0, sizeof(buf));
771 err = read(self->hidraw_fd, buf, sizeof(buf));
772 ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
773 ASSERT_EQ(buf[0], 2);
774 ASSERT_EQ(buf[1], 52);
778 * Call hid_bpf_input_report against the given uhid device,
779 * check that the program is not making infinite loops.
781 TEST_F(hid_bpf, test_hid_infinite_loop_input_report_call)
783 const struct test_program progs[] = {
784 { .name = "hid_test_infinite_loop_input_report" },
786 __u8 buf[10] = {0};
787 int err;
789 LOAD_PROGRAMS(progs);
791 /* emit hid_hw_output_report from hidraw */
792 buf[0] = 1; /* report ID */
793 buf[1] = 2;
794 buf[2] = 42;
796 uhid_send_event(_metadata, &self->hid, buf, 6);
798 /* read the data from hidraw */
799 memset(buf, 0, sizeof(buf));
800 err = read(self->hidraw_fd, buf, sizeof(buf));
801 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
802 ASSERT_EQ(buf[0], 1);
803 ASSERT_EQ(buf[1], 3);
805 /* read the data from hidraw: hid_bpf_try_input_report should work exactly one time */
806 memset(buf, 0, sizeof(buf));
807 err = read(self->hidraw_fd, buf, sizeof(buf));
808 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
809 ASSERT_EQ(buf[0], 1);
810 ASSERT_EQ(buf[1], 4);
812 /* read the data from hidraw: there should be none */
813 memset(buf, 0, sizeof(buf));
814 err = read(self->hidraw_fd, buf, sizeof(buf));
815 ASSERT_EQ(err, -1) TH_LOG("read_hidraw");
819 * Attach hid_insert{0,1,2} to the given uhid device,
820 * retrieve and open the matching hidraw node,
821 * inject one event in the uhid device,
822 * check that the programs have been inserted in the correct order.
824 TEST_F(hid_bpf, test_hid_attach_flags)
826 const struct test_program progs[] = {
828 .name = "hid_test_insert2",
829 .insert_head = 0,
832 .name = "hid_test_insert1",
833 .insert_head = 1,
836 .name = "hid_test_insert3",
837 .insert_head = 0,
840 __u8 buf[10] = {0};
841 int err;
843 LOAD_PROGRAMS(progs);
845 /* inject one event */
846 buf[0] = 1;
847 uhid_send_event(_metadata, &self->hid, buf, 6);
849 /* read the data from hidraw */
850 memset(buf, 0, sizeof(buf));
851 err = read(self->hidraw_fd, buf, sizeof(buf));
852 ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
853 ASSERT_EQ(buf[1], 1);
854 ASSERT_EQ(buf[2], 2);
855 ASSERT_EQ(buf[3], 3);
859 * Attach hid_rdesc_fixup to the given uhid device,
860 * retrieve and open the matching hidraw node,
861 * check that the hidraw report descriptor has been updated.
863 TEST_F(hid_bpf, test_rdesc_fixup)
865 struct hidraw_report_descriptor rpt_desc = {0};
866 const struct test_program progs[] = {
867 { .name = "hid_rdesc_fixup" },
869 int err, desc_size;
871 LOAD_PROGRAMS(progs);
873 /* check that hid_rdesc_fixup() was executed */
874 ASSERT_EQ(self->skel->data->callback2_check, 0x21);
876 /* read the exposed report descriptor from hidraw */
877 err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size);
878 ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGRDESCSIZE: %d", err);
880 /* ensure the new size of the rdesc is bigger than the old one */
881 ASSERT_GT(desc_size, sizeof(rdesc));
883 rpt_desc.size = desc_size;
884 err = ioctl(self->hidraw_fd, HIDIOCGRDESC, &rpt_desc);
885 ASSERT_GE(err, 0) TH_LOG("error while reading HIDIOCGRDESC: %d", err);
887 ASSERT_EQ(rpt_desc.value[4], 0x42);
890 static int libbpf_print_fn(enum libbpf_print_level level,
891 const char *format, va_list args)
893 char buf[1024];
895 if (level == LIBBPF_DEBUG)
896 return 0;
898 snprintf(buf, sizeof(buf), "# %s", format);
900 vfprintf(stdout, buf, args);
901 return 0;
904 int main(int argc, char **argv)
906 /* Use libbpf 1.0 API mode */
907 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
908 libbpf_set_print(libbpf_print_fn);
910 return test_harness_run(argc, argv);