1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Red hat */
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include "hid_bpf_helpers.h"
8 char _license[] SEC("license") = "GPL";
10 struct attach_prog_args {
17 __u64 callback_check = 52;
18 __u64 callback2_check = 52;
20 SEC("?fmod_ret/hid_bpf_device_event")
21 int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx)
23 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
26 return 0; /* EPERM check */
28 callback_check = rw_data[1];
30 rw_data[2] = rw_data[1] + 5;
35 SEC("?fmod_ret/hid_bpf_device_event")
36 int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx)
38 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
41 return 0; /* EPERM check */
43 rw_data[3] = rw_data[2] + 5;
48 SEC("?fmod_ret/hid_bpf_device_event")
49 int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx)
51 __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
54 return 0; /* EPERM check */
62 int attach_prog(struct attach_prog_args *ctx)
64 ctx->retval = hid_bpf_attach_prog(ctx->hid,
66 ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD :
71 struct hid_hw_request_syscall_args {
72 /* data needs to come at offset 0 so we can use it in calls */
77 enum hid_report_type type;
82 int hid_user_raw_request(struct hid_hw_request_syscall_args *args)
84 struct hid_bpf_ctx *ctx;
85 const size_t size = args->size;
88 if (size > sizeof(args->data))
89 return -7; /* -E2BIG */
91 ctx = hid_bpf_allocate_context(args->hid);
93 return -1; /* EPERM check */
95 ret = hid_bpf_hw_request(ctx,
102 hid_bpf_release_context(ctx);
107 static const __u8 rdesc[] = {
108 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
109 0x09, 0x32, /* USAGE (Z) */
110 0x95, 0x01, /* REPORT_COUNT (1) */
111 0x81, 0x06, /* INPUT (Data,Var,Rel) */
113 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
114 0x19, 0x01, /* USAGE_MINIMUM (1) */
115 0x29, 0x03, /* USAGE_MAXIMUM (3) */
116 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
117 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
118 0x95, 0x03, /* REPORT_COUNT (3) */
119 0x75, 0x01, /* REPORT_SIZE (1) */
120 0x91, 0x02, /* Output (Data,Var,Abs) */
121 0x95, 0x01, /* REPORT_COUNT (1) */
122 0x75, 0x05, /* REPORT_SIZE (5) */
123 0x91, 0x01, /* Output (Cnst,Var,Abs) */
125 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
126 0x19, 0x06, /* USAGE_MINIMUM (6) */
127 0x29, 0x08, /* USAGE_MAXIMUM (8) */
128 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
129 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
130 0x95, 0x03, /* REPORT_COUNT (3) */
131 0x75, 0x01, /* REPORT_SIZE (1) */
132 0xb1, 0x02, /* Feature (Data,Var,Abs) */
133 0x95, 0x01, /* REPORT_COUNT (1) */
134 0x75, 0x05, /* REPORT_SIZE (5) */
135 0x91, 0x01, /* Output (Cnst,Var,Abs) */
137 0xc0, /* END_COLLECTION */
138 0xc0, /* END_COLLECTION */
141 SEC("?fmod_ret/hid_bpf_rdesc_fixup")
142 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx)
144 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4096 /* size */);
147 return 0; /* EPERM check */
149 callback2_check = data[4];
151 /* insert rdesc at offset 73 */
152 __builtin_memcpy(&data[73], rdesc, sizeof(rdesc));
154 /* Change Usage Vendor globally */
157 return sizeof(rdesc) + 73;
160 SEC("?fmod_ret/hid_bpf_device_event")
161 int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx)
163 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
166 return 0; /* EPERM check */
168 /* we need to be run first */
169 if (data[2] || data[3])
177 SEC("?fmod_ret/hid_bpf_device_event")
178 int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx)
180 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
183 return 0; /* EPERM check */
185 /* after insert0 and before insert2 */
186 if (!data[1] || data[3])
194 SEC("?fmod_ret/hid_bpf_device_event")
195 int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx)
197 __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
200 return 0; /* EPERM check */
203 if (!data[1] || !data[2])