selftests/hid: add another test for injecting an event from an event hook
Similar to test_multiply_events_wq: we receive one event and inject a new one. But given that this time we are already in the event hook, we can use hid_bpf_try_input_report() directly as this function will not sleep. Note that the injected event gets processed before the original one this way. Link: https://patch.msgid.link/20240626-hid_hw_req_bpf-v2-12-cfd60fb6c79f@kernel.org Acked-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
This commit is contained in:
parent
9acbb7ba45
commit
62f2e1a096
@ -1168,6 +1168,42 @@ TEST_F(hid_bpf, test_multiply_events_wq)
|
||||
ASSERT_EQ(buf[1], 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach hid_multiply_event to the given uhid device,
|
||||
* retrieve and open the matching hidraw node,
|
||||
* inject one event in the uhid device,
|
||||
* check that the program sees it and can add extra data
|
||||
*/
|
||||
TEST_F(hid_bpf, test_multiply_events)
|
||||
{
|
||||
const struct test_program progs[] = {
|
||||
{ .name = "hid_test_multiply_events" },
|
||||
};
|
||||
__u8 buf[10] = {0};
|
||||
int err;
|
||||
|
||||
LOAD_PROGRAMS(progs);
|
||||
|
||||
/* inject one event */
|
||||
buf[0] = 1;
|
||||
buf[1] = 42;
|
||||
uhid_send_event(_metadata, self->uhid_fd, buf, 6);
|
||||
|
||||
/* read the data from hidraw */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
err = read(self->hidraw_fd, buf, sizeof(buf));
|
||||
ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
|
||||
ASSERT_EQ(buf[0], 2);
|
||||
ASSERT_EQ(buf[1], 47);
|
||||
|
||||
/* read the data from hidraw */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
err = read(self->hidraw_fd, buf, sizeof(buf));
|
||||
ASSERT_EQ(err, 9) TH_LOG("read_hidraw");
|
||||
ASSERT_EQ(buf[0], 2);
|
||||
ASSERT_EQ(buf[1], 52);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach hid_insert{0,1,2} to the given uhid device,
|
||||
* retrieve and open the matching hidraw node,
|
||||
|
@ -522,3 +522,42 @@ SEC(".struct_ops.link")
|
||||
struct hid_bpf_ops test_multiply_events_wq = {
|
||||
.hid_device_event = (void *)hid_test_multiply_events_wq,
|
||||
};
|
||||
|
||||
SEC("?struct_ops/hid_device_event")
|
||||
int BPF_PROG(hid_test_multiply_events, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
|
||||
{
|
||||
__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 9 /* size */);
|
||||
__u8 buf[9];
|
||||
int ret;
|
||||
|
||||
if (!data)
|
||||
return 0; /* EPERM check */
|
||||
|
||||
if (data[0] != 1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* we have to use an intermediate buffer as hid_bpf_input_report
|
||||
* will memset data to \0
|
||||
*/
|
||||
__builtin_memcpy(buf, data, sizeof(buf));
|
||||
|
||||
buf[0] = 2;
|
||||
buf[1] += 5;
|
||||
ret = hid_bpf_try_input_report(hid_ctx, HID_INPUT_REPORT, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* In real world we should reset the original buffer as data might be garbage now,
|
||||
* but it actually now has the content of 'buf'
|
||||
*/
|
||||
data[1] += 5;
|
||||
|
||||
return 9;
|
||||
}
|
||||
|
||||
SEC(".struct_ops.link")
|
||||
struct hid_bpf_ops test_multiply_events = {
|
||||
.hid_device_event = (void *)hid_test_multiply_events,
|
||||
};
|
||||
|
@ -89,6 +89,10 @@ extern int hid_bpf_input_report(struct hid_bpf_ctx *ctx,
|
||||
enum hid_report_type type,
|
||||
__u8 *data,
|
||||
size_t buf__sz) __ksym;
|
||||
extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
|
||||
enum hid_report_type type,
|
||||
__u8 *data,
|
||||
size_t buf__sz) __ksym;
|
||||
|
||||
/* bpf_wq implementation */
|
||||
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
|
||||
|
Loading…
Reference in New Issue
Block a user