Commit db624e82 authored by Benjamin Tissoires's avatar Benjamin Tissoires

selftests/hid: Add test for hid_bpf_hw_output_report

This time we need to ensure uhid receives it, thus the new mutex and
condition.

Link: https://lore.kernel.org/r/20240315-b4-hid-bpf-new-funcs-v4-4-079c282469d3@kernel.orgSigned-off-by: default avatarBenjamin Tissoires <bentiss@kernel.org>
parent c8a14959
......@@ -16,6 +16,11 @@
#define SHOW_UHID_DEBUG 0
#define min(a, b) \
({ __typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; })
static unsigned char rdesc[] = {
0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
0x09, 0x21, /* Usage (Vendor Usage 0x21) */
......@@ -111,6 +116,10 @@ struct hid_hw_request_syscall_args {
static pthread_mutex_t uhid_started_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t uhid_output_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t uhid_output_cond = PTHREAD_COND_INITIALIZER;
static unsigned char output_report[10];
/* no need to protect uhid_stopped, only one thread accesses it */
static bool uhid_stopped;
......@@ -205,6 +214,13 @@ static int uhid_event(struct __test_metadata *_metadata, int fd)
break;
case UHID_OUTPUT:
UHID_LOG("UHID_OUTPUT from uhid-dev");
pthread_mutex_lock(&uhid_output_mtx);
memcpy(output_report,
ev.u.output.data,
min(ev.u.output.size, sizeof(output_report)));
pthread_cond_signal(&uhid_output_cond);
pthread_mutex_unlock(&uhid_output_mtx);
break;
case UHID_GET_REPORT:
UHID_LOG("UHID_GET_REPORT from uhid-dev");
......@@ -733,6 +749,53 @@ TEST_F(hid_bpf, test_hid_change_report)
ASSERT_EQ(buf[2], 0) TH_LOG("leftovers_from_previous_test");
}
/*
* Call hid_bpf_hw_output_report against the given uhid device,
* check that the program is called and does the expected.
*/
TEST_F(hid_bpf, test_hid_user_output_report_call)
{
struct hid_hw_request_syscall_args args = {
.retval = -1,
.size = 10,
};
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
.ctx_in = &args,
.ctx_size_in = sizeof(args),
);
int err, cond_err, prog_fd;
struct timespec time_to_wait;
LOAD_BPF;
args.hid = self->hid_id;
args.data[0] = 1; /* report ID */
args.data[1] = 2; /* report ID */
args.data[2] = 42; /* report ID */
prog_fd = bpf_program__fd(self->skel->progs.hid_user_output_report);
pthread_mutex_lock(&uhid_output_mtx);
memset(output_report, 0, sizeof(output_report));
clock_gettime(CLOCK_REALTIME, &time_to_wait);
time_to_wait.tv_sec += 2;
err = bpf_prog_test_run_opts(prog_fd, &tattrs);
cond_err = pthread_cond_timedwait(&uhid_output_cond, &uhid_output_mtx, &time_to_wait);
ASSERT_OK(err) TH_LOG("error while calling bpf_prog_test_run_opts");
ASSERT_OK(cond_err) TH_LOG("error while calling waiting for the condition");
ASSERT_EQ(args.retval, 3);
ASSERT_EQ(output_report[0], 1);
ASSERT_EQ(output_report[1], 2);
ASSERT_EQ(output_report[2], 42);
pthread_mutex_unlock(&uhid_output_mtx);
}
/*
* Attach hid_user_raw_request to the given uhid device,
* call the bpf program from userspace
......
......@@ -101,6 +101,30 @@ int hid_user_raw_request(struct hid_hw_request_syscall_args *args)
return 0;
}
SEC("syscall")
int hid_user_output_report(struct hid_hw_request_syscall_args *args)
{
struct hid_bpf_ctx *ctx;
const size_t size = args->size;
int i, ret = 0;
if (size > sizeof(args->data))
return -7; /* -E2BIG */
ctx = hid_bpf_allocate_context(args->hid);
if (!ctx)
return -1; /* EPERM check */
ret = hid_bpf_hw_output_report(ctx,
args->data,
size);
args->retval = ret;
hid_bpf_release_context(ctx);
return 0;
}
static const __u8 rdesc[] = {
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
0x09, 0x32, /* USAGE (Z) */
......
......@@ -94,5 +94,7 @@ extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx,
size_t buf__sz,
enum hid_report_type type,
enum hid_class_request reqtype) __ksym;
extern int hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx,
__u8 *buf, size_t buf__sz) __ksym;
#endif /* __HID_BPF_HELPERS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment