@@ -17,6 +17,17 @@ static unsigned char rdesc[] = {
0xa1, 0x01, /* COLLECTION (Application) */
0x09, 0x01, /* Usage (Vendor Usage 0x01) */
0xa1, 0x00, /* COLLECTION (Physical) */
+ 0x85, 0x02, /* REPORT_ID (2) */
+ 0x19, 0x01, /* USAGE_MINIMUM (1) */
+ 0x29, 0x08, /* USAGE_MAXIMUM (3) */
+ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
+ 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */
+ 0x95, 0x08, /* REPORT_COUNT (8) */
+ 0x75, 0x08, /* REPORT_SIZE (8) */
+ 0x81, 0x02, /* INPUT (Data,Var,Abs) */
+ 0xc0, /* END_COLLECTION */
+ 0x09, 0x01, /* Usage (Vendor Usage 0x01) */
+ 0xa1, 0x00, /* COLLECTION (Physical) */
0x85, 0x01, /* REPORT_ID (1) */
0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
0x19, 0x01, /* USAGE_MINIMUM (1) */
@@ -635,6 +646,53 @@ static int test_attach_detach(int uhid_fd, int dev_id)
return ret;
}
+/*
+ * Attach hid_change_report_id 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 change the data
+ */
+static int test_hid_change_report(int uhid_fd, int dev_id)
+{
+ struct test_params params;
+ int err, hidraw_fd = -1;
+ u8 buf[10] = {0};
+ int ret = -1;
+
+ err = prep_test(dev_id, "hid_change_report_id", ¶ms);
+ if (!ASSERT_EQ(err, 0, "prep_test(hid_change_report_id)"))
+ goto cleanup;
+
+ hidraw_fd = params.hidraw_fd;
+
+ /* inject one event */
+ buf[0] = 1;
+ buf[1] = 42;
+ send_event(uhid_fd, buf, 6);
+
+ /* read the data from hidraw */
+ memset(buf, 0, sizeof(buf));
+ err = read(hidraw_fd, buf, sizeof(buf));
+ if (!ASSERT_EQ(err, 9, "read_hidraw"))
+ goto cleanup;
+
+ if (!ASSERT_EQ(buf[0], 2, "hid_change_report_id"))
+ goto cleanup;
+
+ if (!ASSERT_EQ(buf[1], 42, "hid_change_report_id"))
+ goto cleanup;
+
+ if (!ASSERT_EQ(buf[2], 0, "leftovers_from_previous_test"))
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ cleanup_test(¶ms);
+
+ return ret;
+}
+
void serial_test_hid_bpf(void)
{
int err, uhid_fd;
@@ -660,6 +718,8 @@ void serial_test_hid_bpf(void)
ASSERT_OK(err, "hid");
err = test_attach_detach(uhid_fd, dev_id);
ASSERT_OK(err, "hid_attach_detach");
+ err = test_hid_change_report(uhid_fd, dev_id);
+ ASSERT_OK(err, "hid_change_report");
destroy(uhid_fd);
@@ -32,7 +32,20 @@ int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx)
rw_data[2] = rw_data[1] + 5;
- return 0;
+ return hid_ctx->size;
+}
+
+SEC("?fmod_ret/hid_bpf_device_event")
+int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx)
+{
+ __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
+
+ if (!rw_data)
+ return 0; /* EPERM check */
+
+ rw_data[0] = 2;
+
+ return 9;
}
SEC("syscall")
Use a different report with a bigger size and ensures we are doing things properly. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> --- new in v5 --- tools/testing/selftests/bpf/prog_tests/hid.c | 60 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/hid.c | 15 ++++- 2 files changed, 74 insertions(+), 1 deletion(-)