| 1 | |
| 2 | |
| 3 |
|
| 4 |
|
| 5 | #include "vmlinux.h"
|
| 6 | #include <bpf/bpf_helpers.h>
|
| 7 | #include <bpf/bpf_tracing.h>
|
| 8 | #include "hid_bpf_helpers.h"
|
| 9 |
|
| 10 | #define HID_UP_BUTTON 0x0009
|
| 11 | #define HID_GD_WHEEL 0x0038
|
| 12 |
|
| 13 | SEC("struct_ops/hid_device_event")
|
| 14 | int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)
|
| 15 | {
|
| 16 | __u8 *data = hid_bpf_get_data(hctx, 0 , 9 );
|
| 17 |
|
| 18 | if (!data)
|
| 19 | return 0;
|
| 20 |
|
| 21 |
|
| 22 | data[1] &= 0xfd;
|
| 23 |
|
| 24 |
|
| 25 | data[4] = 0;
|
| 26 | data[5] = 0;
|
| 27 |
|
| 28 |
|
| 29 | data[6] = 0;
|
| 30 | data[7] = 0;
|
| 31 |
|
| 32 | return 0;
|
| 33 | }
|
| 34 |
|
| 35 |
|
| 36 | int resolution = 72;
|
| 37 | int physical = 5;
|
| 38 |
|
| 39 | struct haptic_syscall_args {
|
| 40 | unsigned int hid;
|
| 41 | int retval;
|
| 42 | };
|
| 43 |
|
| 44 | static __u8 haptic_data[8];
|
| 45 |
|
| 46 | SEC("syscall")
|
| 47 | int set_haptic(struct haptic_syscall_args *args)
|
| 48 | {
|
| 49 | struct hid_bpf_ctx *ctx;
|
| 50 | const size_t size = sizeof(haptic_data);
|
| 51 | u16 *res;
|
| 52 | int ret;
|
| 53 |
|
| 54 | if (size > sizeof(haptic_data))
|
| 55 | return -7;
|
| 56 |
|
| 57 | ctx = hid_bpf_allocate_context(args->hid);
|
| 58 | if (!ctx)
|
| 59 | return -1;
|
| 60 |
|
| 61 | haptic_data[0] = 1;
|
| 62 |
|
| 63 | ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
|
| 64 |
|
| 65 | bpf_printk("probed/remove event ret value: %d", ret);
|
| 66 | bpf_printk("buf: %02x %02x %02x",
|
| 67 | haptic_data[0],
|
| 68 | haptic_data[1],
|
| 69 | haptic_data[2]);
|
| 70 | bpf_printk(" %02x %02x %02x",
|
| 71 | haptic_data[3],
|
| 72 | haptic_data[4],
|
| 73 | haptic_data[5]);
|
| 74 | bpf_printk(" %02x %02x",
|
| 75 | haptic_data[6],
|
| 76 | haptic_data[7]);
|
| 77 |
|
| 78 |
|
| 79 | res = (u16 *)&haptic_data[1];
|
| 80 | if (*res != 3600) {
|
| 81 | |
| 82 | |
| 83 | |
| 84 | haptic_data[4] = 3;
|
| 85 | |
| 86 | |
| 87 | |
| 88 | } else {
|
| 89 | haptic_data[4] = 0;
|
| 90 | }
|
| 91 |
|
| 92 | ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
| 93 |
|
| 94 | bpf_printk("set haptic ret value: %d -> %d", ret, haptic_data[4]);
|
| 95 |
|
| 96 | args->retval = ret;
|
| 97 |
|
| 98 | hid_bpf_release_context(ctx);
|
| 99 |
|
| 100 | return 0;
|
| 101 | }
|
| 102 |
|
| 103 |
|
| 104 | SEC("struct_ops/hid_rdesc_fixup")
|
| 105 | int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
|
| 106 | {
|
| 107 | __u8 *data = hid_bpf_get_data(hctx, 0 , 4096 );
|
| 108 | __u16 *res, *phys;
|
| 109 |
|
| 110 | if (!data)
|
| 111 | return 0;
|
| 112 |
|
| 113 |
|
| 114 | data[31] = HID_UP_BUTTON;
|
| 115 | data[33] = 2;
|
| 116 |
|
| 117 |
|
| 118 | data[45] = HID_GD_WHEEL;
|
| 119 |
|
| 120 |
|
| 121 | phys = (__u16 *)&data[61];
|
| 122 | *phys = physical;
|
| 123 | res = (__u16 *)&data[66];
|
| 124 | *res = resolution;
|
| 125 |
|
| 126 |
|
| 127 | data[88] = 0x06;
|
| 128 | data[98] = 0x06;
|
| 129 |
|
| 130 | return 0;
|
| 131 | }
|
| 132 |
|
| 133 | SEC(".struct_ops.link")
|
| 134 | struct hid_bpf_ops surface_dial = {
|
| 135 | .hid_rdesc_fixup = (void *)hid_rdesc_fixup,
|
| 136 | .hid_device_event = (void *)hid_event,
|
| 137 | };
|
| 138 |
|
| 139 | char _license[] SEC("license") = "GPL";
|
| 140 | u32 _version SEC("version") = 1;
|