]> Git Repo - J-linux.git/blob - tools/testing/selftests/hid/progs/hid.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.git] / tools / testing / selftests / hid / progs / hid.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Red hat */
3 #include "vmlinux.h"
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include "hid_bpf_helpers.h"
7
8 char _license[] SEC("license") = "GPL";
9
10 struct attach_prog_args {
11         int prog_fd;
12         unsigned int hid;
13         int retval;
14         int insert_head;
15 };
16
17 __u64 callback_check = 52;
18 __u64 callback2_check = 52;
19
20 SEC("?fmod_ret/hid_bpf_device_event")
21 int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx)
22 {
23         __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
24
25         if (!rw_data)
26                 return 0; /* EPERM check */
27
28         callback_check = rw_data[1];
29
30         rw_data[2] = rw_data[1] + 5;
31
32         return hid_ctx->size;
33 }
34
35 SEC("?fmod_ret/hid_bpf_device_event")
36 int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx)
37 {
38         __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
39
40         if (!rw_data)
41                 return 0; /* EPERM check */
42
43         rw_data[3] = rw_data[2] + 5;
44
45         return hid_ctx->size;
46 }
47
48 SEC("?fmod_ret/hid_bpf_device_event")
49 int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx)
50 {
51         __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
52
53         if (!rw_data)
54                 return 0; /* EPERM check */
55
56         rw_data[0] = 2;
57
58         return 9;
59 }
60
61 SEC("syscall")
62 int attach_prog(struct attach_prog_args *ctx)
63 {
64         ctx->retval = hid_bpf_attach_prog(ctx->hid,
65                                           ctx->prog_fd,
66                                           ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD :
67                                                              HID_BPF_FLAG_NONE);
68         return 0;
69 }
70
71 struct hid_hw_request_syscall_args {
72         /* data needs to come at offset 0 so we can use it in calls */
73         __u8 data[10];
74         unsigned int hid;
75         int retval;
76         size_t size;
77         enum hid_report_type type;
78         __u8 request_type;
79 };
80
81 SEC("syscall")
82 int hid_user_raw_request(struct hid_hw_request_syscall_args *args)
83 {
84         struct hid_bpf_ctx *ctx;
85         const size_t size = args->size;
86         int i, ret = 0;
87
88         if (size > sizeof(args->data))
89                 return -7; /* -E2BIG */
90
91         ctx = hid_bpf_allocate_context(args->hid);
92         if (!ctx)
93                 return -1; /* EPERM check */
94
95         ret = hid_bpf_hw_request(ctx,
96                                  args->data,
97                                  size,
98                                  args->type,
99                                  args->request_type);
100         args->retval = ret;
101
102         hid_bpf_release_context(ctx);
103
104         return 0;
105 }
106
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) */
112
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) */
124
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) */
136
137         0xc0,                           /* END_COLLECTION */
138         0xc0,                   /* END_COLLECTION */
139 };
140
141 SEC("?fmod_ret/hid_bpf_rdesc_fixup")
142 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx)
143 {
144         __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4096 /* size */);
145
146         if (!data)
147                 return 0; /* EPERM check */
148
149         callback2_check = data[4];
150
151         /* insert rdesc at offset 73 */
152         __builtin_memcpy(&data[73], rdesc, sizeof(rdesc));
153
154         /* Change Usage Vendor globally */
155         data[4] = 0x42;
156
157         return sizeof(rdesc) + 73;
158 }
159
160 SEC("?fmod_ret/hid_bpf_device_event")
161 int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx)
162 {
163         __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
164
165         if (!data)
166                 return 0; /* EPERM check */
167
168         /* we need to be run first */
169         if (data[2] || data[3])
170                 return -1;
171
172         data[1] = 1;
173
174         return 0;
175 }
176
177 SEC("?fmod_ret/hid_bpf_device_event")
178 int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx)
179 {
180         __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
181
182         if (!data)
183                 return 0; /* EPERM check */
184
185         /* after insert0 and before insert2 */
186         if (!data[1] || data[3])
187                 return -1;
188
189         data[2] = 2;
190
191         return 0;
192 }
193
194 SEC("?fmod_ret/hid_bpf_device_event")
195 int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx)
196 {
197         __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
198
199         if (!data)
200                 return 0; /* EPERM check */
201
202         /* at the end */
203         if (!data[1] || !data[2])
204                 return -1;
205
206         data[3] = 3;
207
208         return 0;
209 }
This page took 0.043416 seconds and 4 git commands to generate.