Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include "vmlinux.h"
  4#include <bpf/bpf_helpers.h>
  5#include <bpf/bpf_tracing.h>
  6#include "hid_bpf_helpers.h"
  7
  8static int hid_y_event(struct hid_bpf_ctx *hctx)
  9{
 10	s16 y;
 11	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
 12
 13	if (!data)
 14		return 0; /* EPERM check */
 15
 16	bpf_printk("event: size: %d", hctx->size);
 17	bpf_printk("incoming event: %02x %02x %02x",
 18		   data[0],
 19		   data[1],
 20		   data[2]);
 21	bpf_printk("                %02x %02x %02x",
 22		   data[3],
 23		   data[4],
 24		   data[5]);
 25	bpf_printk("                %02x %02x %02x",
 26		   data[6],
 27		   data[7],
 28		   data[8]);
 29
 30	y = data[3] | (data[4] << 8);
 31
 32	y = -y;
 33
 34	data[3] = y & 0xFF;
 35	data[4] = (y >> 8) & 0xFF;
 36
 37	bpf_printk("modified event: %02x %02x %02x",
 38		   data[0],
 39		   data[1],
 40		   data[2]);
 41	bpf_printk("                %02x %02x %02x",
 42		   data[3],
 43		   data[4],
 44		   data[5]);
 45	bpf_printk("                %02x %02x %02x",
 46		   data[6],
 47		   data[7],
 48		   data[8]);
 49
 50	return 0;
 51}
 52
 53static int hid_x_event(struct hid_bpf_ctx *hctx)
 54{
 55	s16 x;
 56	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
 57
 58	if (!data)
 59		return 0; /* EPERM check */
 60
 61	x = data[1] | (data[2] << 8);
 62
 63	x = -x;
 64
 65	data[1] = x & 0xFF;
 66	data[2] = (x >> 8) & 0xFF;
 67	return 0;
 68}
 69
 70SEC("struct_ops/hid_device_event")
 71int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type)
 72{
 73	int ret = hid_y_event(hctx);
 74
 75	if (ret)
 76		return ret;
 77
 78	return hid_x_event(hctx);
 79}
 80
 81
 82SEC("struct_ops/hid_rdesc_fixup")
 83int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
 84{
 85	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
 86
 87	if (!data)
 88		return 0; /* EPERM check */
 89
 90	bpf_printk("rdesc: %02x %02x %02x",
 91		   data[0],
 92		   data[1],
 93		   data[2]);
 94	bpf_printk("       %02x %02x %02x",
 95		   data[3],
 96		   data[4],
 97		   data[5]);
 98	bpf_printk("       %02x %02x %02x ...",
 99		   data[6],
100		   data[7],
101		   data[8]);
102
103	/*
104	 * The original report descriptor contains:
105	 *
106	 * 0x05, 0x01,                    //   Usage Page (Generic Desktop)      30
107	 * 0x16, 0x01, 0x80,              //   Logical Minimum (-32767)          32
108	 * 0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           35
109	 * 0x09, 0x30,                    //   Usage (X)                         38
110	 * 0x09, 0x31,                    //   Usage (Y)                         40
111	 *
112	 * So byte 39 contains Usage X and byte 41 Usage Y.
113	 *
114	 * We simply swap the axes here.
115	 */
116	data[39] = 0x31;
117	data[41] = 0x30;
118
119	return 0;
120}
121
122SEC(".struct_ops.link")
123struct hid_bpf_ops mouse_invert = {
124	.hid_rdesc_fixup = (void *)hid_rdesc_fixup,
125	.hid_device_event = (void *)hid_event,
126};
127
128char _license[] SEC("license") = "GPL";