| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // SPDX-License-Identifier: GPL-2.0-only
- /* Copyright (c) 2022 Benjamin Tissoires
- */
- #include "vmlinux.h"
- #include <bpf/bpf_helpers.h>
- #include <bpf/bpf_tracing.h>
- #include "hid_bpf_helpers.h"
- #define HID_UP_BUTTON 0x0009
- #define HID_GD_WHEEL 0x0038
- SEC("struct_ops/hid_device_event")
- int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)
- {
- __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
- if (!data)
- return 0; /* EPERM check */
- /* Touch */
- data[1] &= 0xfd;
- /* X */
- data[4] = 0;
- data[5] = 0;
- /* Y */
- data[6] = 0;
- data[7] = 0;
- return 0;
- }
- /* 72 == 360 / 5 -> 1 report every 5 degrees */
- int resolution = 72;
- int physical = 5;
- struct haptic_syscall_args {
- unsigned int hid;
- int retval;
- };
- static __u8 haptic_data[8];
- SEC("syscall")
- int set_haptic(struct haptic_syscall_args *args)
- {
- struct hid_bpf_ctx *ctx;
- const size_t size = sizeof(haptic_data);
- u16 *res;
- int ret;
- if (size > sizeof(haptic_data))
- return -7; /* -E2BIG */
- ctx = hid_bpf_allocate_context(args->hid);
- if (!ctx)
- return -1; /* EPERM check */
- haptic_data[0] = 1; /* report ID */
- ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
- bpf_printk("probed/remove event ret value: %d", ret);
- bpf_printk("buf: %02x %02x %02x",
- haptic_data[0],
- haptic_data[1],
- haptic_data[2]);
- bpf_printk(" %02x %02x %02x",
- haptic_data[3],
- haptic_data[4],
- haptic_data[5]);
- bpf_printk(" %02x %02x",
- haptic_data[6],
- haptic_data[7]);
- /* whenever resolution multiplier is not 3600, we have the fixed report descriptor */
- res = (u16 *)&haptic_data[1];
- if (*res != 3600) {
- // haptic_data[1] = 72; /* resolution multiplier */
- // haptic_data[2] = 0; /* resolution multiplier */
- // haptic_data[3] = 0; /* Repeat Count */
- haptic_data[4] = 3; /* haptic Auto Trigger */
- // haptic_data[5] = 5; /* Waveform Cutoff Time */
- // haptic_data[6] = 80; /* Retrigger Period */
- // haptic_data[7] = 0; /* Retrigger Period */
- } else {
- haptic_data[4] = 0;
- }
- ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- bpf_printk("set haptic ret value: %d -> %d", ret, haptic_data[4]);
- args->retval = ret;
- hid_bpf_release_context(ctx);
- return 0;
- }
- /* Convert REL_DIAL into REL_WHEEL */
- SEC("struct_ops/hid_rdesc_fixup")
- int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
- {
- __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
- __u16 *res, *phys;
- if (!data)
- return 0; /* EPERM check */
- /* Convert TOUCH into a button */
- data[31] = HID_UP_BUTTON;
- data[33] = 2;
- /* Convert REL_DIAL into REL_WHEEL */
- data[45] = HID_GD_WHEEL;
- /* Change Resolution Multiplier */
- phys = (__u16 *)&data[61];
- *phys = physical;
- res = (__u16 *)&data[66];
- *res = resolution;
- /* Convert X,Y from Abs to Rel */
- data[88] = 0x06;
- data[98] = 0x06;
- return 0;
- }
- SEC(".struct_ops.link")
- struct hid_bpf_ops surface_dial = {
- .hid_rdesc_fixup = (void *)hid_rdesc_fixup,
- .hid_device_event = (void *)hid_event,
- };
- char _license[] SEC("license") = "GPL";
- u32 _version SEC("version") = 1;
|