6008105b4f
Everything should be available in the selftest part of the tree, but providing an example without uhid and hidraw will be more easy to follow for users. This example will probably ever only work on the Etekcity Scroll 6E because we need to adapt the various raw values to the actual device. On that device, the X and Y axis will be swapped and inverted, and on any other device, chances are high that the device will not work until Ctrl-C is hit. The Makefiles are taken from samples/bpf to not reinvent the wheel and to force using in-kernel libbpf and bpftool. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
113 lines
2.4 KiB
C
113 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include "vmlinux.h"
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
#include "hid_bpf_helpers.h"
|
|
|
|
SEC("fmod_ret/hid_bpf_device_event")
|
|
int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx)
|
|
{
|
|
s16 y;
|
|
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
|
|
|
|
if (!data)
|
|
return 0; /* EPERM check */
|
|
|
|
bpf_printk("event: size: %d", hctx->size);
|
|
bpf_printk("incoming event: %02x %02x %02x",
|
|
data[0],
|
|
data[1],
|
|
data[2]);
|
|
bpf_printk(" %02x %02x %02x",
|
|
data[3],
|
|
data[4],
|
|
data[5]);
|
|
bpf_printk(" %02x %02x %02x",
|
|
data[6],
|
|
data[7],
|
|
data[8]);
|
|
|
|
y = data[3] | (data[4] << 8);
|
|
|
|
y = -y;
|
|
|
|
data[3] = y & 0xFF;
|
|
data[4] = (y >> 8) & 0xFF;
|
|
|
|
bpf_printk("modified event: %02x %02x %02x",
|
|
data[0],
|
|
data[1],
|
|
data[2]);
|
|
bpf_printk(" %02x %02x %02x",
|
|
data[3],
|
|
data[4],
|
|
data[5]);
|
|
bpf_printk(" %02x %02x %02x",
|
|
data[6],
|
|
data[7],
|
|
data[8]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("fmod_ret/hid_bpf_device_event")
|
|
int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx)
|
|
{
|
|
s16 x;
|
|
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
|
|
|
|
if (!data)
|
|
return 0; /* EPERM check */
|
|
|
|
x = data[1] | (data[2] << 8);
|
|
|
|
x = -x;
|
|
|
|
data[1] = x & 0xFF;
|
|
data[2] = (x >> 8) & 0xFF;
|
|
return 0;
|
|
}
|
|
|
|
SEC("fmod_ret/hid_bpf_rdesc_fixup")
|
|
int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
|
|
{
|
|
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
|
|
|
|
if (!data)
|
|
return 0; /* EPERM check */
|
|
|
|
bpf_printk("rdesc: %02x %02x %02x",
|
|
data[0],
|
|
data[1],
|
|
data[2]);
|
|
bpf_printk(" %02x %02x %02x",
|
|
data[3],
|
|
data[4],
|
|
data[5]);
|
|
bpf_printk(" %02x %02x %02x ...",
|
|
data[6],
|
|
data[7],
|
|
data[8]);
|
|
|
|
/*
|
|
* The original report descriptor contains:
|
|
*
|
|
* 0x05, 0x01, // Usage Page (Generic Desktop) 30
|
|
* 0x16, 0x01, 0x80, // Logical Minimum (-32767) 32
|
|
* 0x26, 0xff, 0x7f, // Logical Maximum (32767) 35
|
|
* 0x09, 0x30, // Usage (X) 38
|
|
* 0x09, 0x31, // Usage (Y) 40
|
|
*
|
|
* So byte 39 contains Usage X and byte 41 Usage Y.
|
|
*
|
|
* We simply swap the axes here.
|
|
*/
|
|
data[39] = 0x31;
|
|
data[41] = 0x30;
|
|
|
|
return 0;
|
|
}
|
|
|
|
char _license[] SEC("license") = "GPL";
|