summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/hid/progs/hid.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <bentiss@kernel.org>2024-06-26 15:46:31 +0200
committerBenjamin Tissoires <bentiss@kernel.org>2024-06-27 11:00:48 +0200
commitfe8d561db3e82a1130c59ebc143d557b0bdb0cff (patch)
tree8fe5ee74baf94901735e754336b6fd91b1cd1b2d /tools/testing/selftests/hid/progs/hid.c
parentfa03f398a8ac46f46927e0b509b302ebe0ed7e8a (diff)
downloadlinux-next-fe8d561db3e82a1130c59ebc143d557b0bdb0cff.tar.gz
linux-next-fe8d561db3e82a1130c59ebc143d557b0bdb0cff.zip
selftests/hid: add wq test for hid_bpf_input_report()
Now that bpf_wq is available, we can write a test with it. Having hid_bpf_input_report() waiting for the device means that we can directly call it, and we get that event when the device is ready. Link: https://patch.msgid.link/20240626-hid_hw_req_bpf-v2-10-cfd60fb6c79f@kernel.org Acked-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Diffstat (limited to 'tools/testing/selftests/hid/progs/hid.c')
-rw-r--r--tools/testing/selftests/hid/progs/hid.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c
index 1fa288b76cd5..f539a7a223cf 100644
--- a/tools/testing/selftests/hid/progs/hid.c
+++ b/tools/testing/selftests/hid/progs/hid.c
@@ -443,3 +443,82 @@ SEC(".struct_ops.link")
struct hid_bpf_ops test_infinite_loop_output_report = {
.hid_hw_output_report = (void *)hid_test_infinite_loop_output_report,
};
+
+struct elem {
+ struct bpf_wq work;
+};
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(max_entries, 1);
+ __type(key, int);
+ __type(value, struct elem);
+} hmap SEC(".maps");
+
+static int wq_cb_sleepable(void *map, int *key, struct bpf_wq *work)
+{
+ __u8 buf[9] = {2, 3, 4, 5, 6, 7, 8, 9, 10};
+ struct hid_bpf_ctx *hid_ctx;
+
+ hid_ctx = hid_bpf_allocate_context(*key);
+ if (!hid_ctx)
+ return 0; /* EPERM check */
+
+ hid_bpf_input_report(hid_ctx, HID_INPUT_REPORT, buf, sizeof(buf));
+
+ hid_bpf_release_context(hid_ctx);
+
+ return 0;
+}
+
+static int test_inject_input_report_callback(int *key)
+{
+ struct elem init = {}, *val;
+ struct bpf_wq *wq;
+
+ if (bpf_map_update_elem(&hmap, key, &init, 0))
+ return -1;
+
+ val = bpf_map_lookup_elem(&hmap, key);
+ if (!val)
+ return -2;
+
+ wq = &val->work;
+ if (bpf_wq_init(wq, &hmap, 0) != 0)
+ return -3;
+
+ if (bpf_wq_set_callback(wq, wq_cb_sleepable, 0))
+ return -4;
+
+ if (bpf_wq_start(wq, 0))
+ return -5;
+
+ return 0;
+}
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_test_multiply_events_wq, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
+{
+ __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 9 /* size */);
+ int hid = hid_ctx->hid->id;
+ int ret;
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ if (data[0] != 1)
+ return 0;
+
+ ret = test_inject_input_report_callback(&hid);
+ if (ret)
+ return ret;
+
+ data[1] += 5;
+
+ return 0;
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops test_multiply_events_wq = {
+ .hid_device_event = (void *)hid_test_multiply_events_wq,
+};