141 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2022 Benjamin Tissoires3 */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 0x000911#define HID_GD_WHEEL 0x003812 13SEC("struct_ops/hid_device_event")14int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)15{16 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);17 18 if (!data)19 return 0; /* EPERM check */20 21 /* Touch */22 data[1] &= 0xfd;23 24 /* X */25 data[4] = 0;26 data[5] = 0;27 28 /* Y */29 data[6] = 0;30 data[7] = 0;31 32 return 0;33}34 35/* 72 == 360 / 5 -> 1 report every 5 degrees */36int resolution = 72;37int physical = 5;38 39struct haptic_syscall_args {40 unsigned int hid;41 int retval;42};43 44static __u8 haptic_data[8];45 46SEC("syscall")47int 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; /* -E2BIG */56 57 ctx = hid_bpf_allocate_context(args->hid);58 if (!ctx)59 return -1; /* EPERM check */60 61 haptic_data[0] = 1; /* report ID */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 /* whenever resolution multiplier is not 3600, we have the fixed report descriptor */79 res = (u16 *)&haptic_data[1];80 if (*res != 3600) {81// haptic_data[1] = 72; /* resolution multiplier */82// haptic_data[2] = 0; /* resolution multiplier */83// haptic_data[3] = 0; /* Repeat Count */84 haptic_data[4] = 3; /* haptic Auto Trigger */85// haptic_data[5] = 5; /* Waveform Cutoff Time */86// haptic_data[6] = 80; /* Retrigger Period */87// haptic_data[7] = 0; /* Retrigger Period */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/* Convert REL_DIAL into REL_WHEEL */104SEC("struct_ops/hid_rdesc_fixup")105int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)106{107 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);108 __u16 *res, *phys;109 110 if (!data)111 return 0; /* EPERM check */112 113 /* Convert TOUCH into a button */114 data[31] = HID_UP_BUTTON;115 data[33] = 2;116 117 /* Convert REL_DIAL into REL_WHEEL */118 data[45] = HID_GD_WHEEL;119 120 /* Change Resolution Multiplier */121 phys = (__u16 *)&data[61];122 *phys = physical;123 res = (__u16 *)&data[66];124 *res = resolution;125 126 /* Convert X,Y from Abs to Rel */127 data[88] = 0x06;128 data[98] = 0x06;129 130 return 0;131}132 133SEC(".struct_ops.link")134struct hid_bpf_ops surface_dial = {135 .hid_rdesc_fixup = (void *)hid_rdesc_fixup,136 .hid_device_event = (void *)hid_event,137};138 139char _license[] SEC("license") = "GPL";140u32 _version SEC("version") = 1;141