191 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2024 Benjamin Tissoires3 */4 5#include "vmlinux.h"6#include "hid_bpf.h"7#include "hid_bpf_helpers.h"8#include <bpf/bpf_tracing.h>9 10#define VID_BETOP_2185PC 0x11C011#define PID_RAPTOR_MACH_2 0x560612 13HID_BPF_CONFIG(14 HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_BETOP_2185PC, PID_RAPTOR_MACH_2),15);16 17/*18 * For reference, this is the fixed report descriptor19 *20 * static const __u8 fixed_rdesc[] = {21 * 0x05, 0x01, // Usage Page (Generic Desktop) 022 * 0x09, 0x04, // Usage (Joystick) 223 * 0xa1, 0x01, // Collection (Application) 424 * 0x05, 0x01, // Usage Page (Generic Desktop) 625 * 0x85, 0x01, // Report ID (1) 826 * 0x05, 0x01, // Usage Page (Generic Desktop) 1027 * 0x09, 0x30, // Usage (X) 1228 * 0x75, 0x10, // Report Size (16) 1429 * 0x95, 0x01, // Report Count (1) 1630 * 0x15, 0x00, // Logical Minimum (0) 1831 * 0x26, 0xff, 0x07, // Logical Maximum (2047) 2032 * 0x46, 0xff, 0x07, // Physical Maximum (2047) 2333 * 0x81, 0x02, // Input (Data,Var,Abs) 2634 * 0x05, 0x01, // Usage Page (Generic Desktop) 2835 * 0x09, 0x31, // Usage (Y) 3036 * 0x75, 0x10, // Report Size (16) 3237 * 0x95, 0x01, // Report Count (1) 3438 * 0x15, 0x00, // Logical Minimum (0) 3639 * 0x26, 0xff, 0x07, // Logical Maximum (2047) 3840 * 0x46, 0xff, 0x07, // Physical Maximum (2047) 4141 * 0x81, 0x02, // Input (Data,Var,Abs) 4442 * 0x05, 0x01, // Usage Page (Generic Desktop) 4643 * 0x09, 0x33, // Usage (Rx) 4844 * 0x75, 0x10, // Report Size (16) 5045 * 0x95, 0x01, // Report Count (1) 5246 * 0x15, 0x00, // Logical Minimum (0) 5447 * 0x26, 0xff, 0x03, // Logical Maximum (1023) 5648 * 0x46, 0xff, 0x03, // Physical Maximum (1023) 5949 * 0x81, 0x02, // Input (Data,Var,Abs) 6250 * 0x05, 0x00, // Usage Page (Undefined) 6451 * 0x09, 0x00, // Usage (Undefined) 6652 * 0x75, 0x10, // Report Size (16) 6853 * 0x95, 0x01, // Report Count (1) 7054 * 0x15, 0x00, // Logical Minimum (0) 7255 * 0x26, 0xff, 0x03, // Logical Maximum (1023) 7456 * 0x46, 0xff, 0x03, // Physical Maximum (1023) 7757 * 0x81, 0x02, // Input (Data,Var,Abs) 8058 * 0x05, 0x01, // Usage Page (Generic Desktop) 8259 * 0x09, 0x32, // Usage (Z) 8460 * 0x75, 0x10, // Report Size (16) 8661 * 0x95, 0x01, // Report Count (1) 8862 * 0x15, 0x00, // Logical Minimum (0) 9063 * 0x26, 0xff, 0x03, // Logical Maximum (1023) 9264 * 0x46, 0xff, 0x03, // Physical Maximum (1023) 9565 * 0x81, 0x02, // Input (Data,Var,Abs) 9866 * 0x05, 0x01, // Usage Page (Generic Desktop) 10067 * 0x09, 0x35, // Usage (Rz) 10268 * 0x75, 0x10, // Report Size (16) 10469 * 0x95, 0x01, // Report Count (1) 10670 * 0x15, 0x00, // Logical Minimum (0) 10871 * 0x26, 0xff, 0x03, // Logical Maximum (1023) 11072 * 0x46, 0xff, 0x03, // Physical Maximum (1023) 11373 * 0x81, 0x02, // Input (Data,Var,Abs) 11674 * 0x05, 0x01, // Usage Page (Generic Desktop) 11875 * 0x09, 0x34, // Usage (Ry) 12076 * 0x75, 0x10, // Report Size (16) 12277 * 0x95, 0x01, // Report Count (1) 12478 * 0x15, 0x00, // Logical Minimum (0) 12679 * 0x26, 0xff, 0x07, // Logical Maximum (2047) 12880 * 0x46, 0xff, 0x07, // Physical Maximum (2047) 13181 * 0x81, 0x02, // Input (Data,Var,Abs) 13482 * 0x05, 0x01, // Usage Page (Generic Desktop) 13683 * 0x09, 0x36, // Usage (Slider) 13884 * 0x75, 0x10, // Report Size (16) 14085 * 0x95, 0x01, // Report Count (1) 14286 * 0x15, 0x00, // Logical Minimum (0) 14487 * 0x26, 0xff, 0x03, // Logical Maximum (1023) 14688 * 0x46, 0xff, 0x03, // Physical Maximum (1023) 14989 * 0x81, 0x02, // Input (Data,Var,Abs) 15290 * 0x05, 0x09, // Usage Page (Button) 15491 * 0x19, 0x01, // Usage Minimum (1) 15692 * 0x2a, 0x1d, 0x00, // Usage Maximum (29) 15893 * 0x15, 0x00, // Logical Minimum (0) 16194 * 0x25, 0x01, // Logical Maximum (1) 16395 * 0x75, 0x01, // Report Size (1) 16596 * 0x96, 0x80, 0x00, // Report Count (128) 16797 * 0x81, 0x02, // Input (Data,Var,Abs) 17098 * 0x05, 0x01, // Usage Page (Generic Desktop) 17299 * 0x09, 0x39, // Usage (Hat switch) 174100 * 0x26, 0x07, 0x00, // Logical Maximum (7) 176 // changed (was 239)101 * 0x46, 0x68, 0x01, // Physical Maximum (360) 179102 * 0x65, 0x14, // Unit (EnglishRotation: deg) 182103 * 0x75, 0x10, // Report Size (16) 184104 * 0x95, 0x01, // Report Count (1) 186105 * 0x81, 0x42, // Input (Data,Var,Abs,Null) 188106 * 0x05, 0x01, // Usage Page (Generic Desktop) 190107 * 0x09, 0x00, // Usage (Undefined) 192108 * 0x75, 0x08, // Report Size (8) 194109 * 0x95, 0x1d, // Report Count (29) 196110 * 0x81, 0x01, // Input (Cnst,Arr,Abs) 198111 * 0x15, 0x00, // Logical Minimum (0) 200112 * 0x26, 0xef, 0x00, // Logical Maximum (239) 202113 * 0x85, 0x58, // Report ID (88) 205114 * 0x26, 0xff, 0x00, // Logical Maximum (255) 207115 * 0x46, 0xff, 0x00, // Physical Maximum (255) 210116 * 0x75, 0x08, // Report Size (8) 213117 * 0x95, 0x3f, // Report Count (63) 215118 * 0x09, 0x00, // Usage (Undefined) 217119 * 0x91, 0x02, // Output (Data,Var,Abs) 219120 * 0x85, 0x59, // Report ID (89) 221121 * 0x75, 0x08, // Report Size (8) 223122 * 0x95, 0x80, // Report Count (128) 225123 * 0x09, 0x00, // Usage (Undefined) 227124 * 0xb1, 0x02, // Feature (Data,Var,Abs) 229125 * 0xc0, // End Collection 231126 * };127 */128 129/*130 * We need to amend the report descriptor for the following:131 * - the joystick sends its hat_switch data between 0 and 239 but132 * the kernel expects the logical max to stick into a signed 8 bits133 * integer. We thus divide it by 30 to match what other joysticks are134 * doing135 */136SEC(HID_BPF_RDESC_FIXUP)137int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)138{139 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);140 141 if (!data)142 return 0; /* EPERM check */143 144 data[177] = 0x07;145 146 return 0;147}148 149/*150 * The hat_switch value at offsets 33 and 34 (16 bits) needs151 * to be reduced to a single 8 bit signed integer. So we152 * divide it by 30.153 * Byte 34 is always null, so it is ignored.154 */155SEC(HID_BPF_DEVICE_EVENT)156int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)157{158 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 64 /* size */);159 160 if (!data)161 return 0; /* EPERM check */162 163 if (data[0] != 0x01) /* not the joystick report ID */164 return 0;165 166 data[33] /= 30;167 168 return 0;169}170 171HID_BPF_OPS(raptor_mach_2) = {172 .hid_rdesc_fixup = (void *)hid_fix_rdesc_raptor_mach_2,173 .hid_device_event = (void *)raptor_mach_2_fix_hat_switch,174};175 176SEC("syscall")177int probe(struct hid_bpf_probe_args *ctx)178{179 ctx->retval = ctx->rdesc_size != 232;180 if (ctx->retval)181 ctx->retval = -EINVAL;182 183 /* ensure the kernel isn't fixed already */184 if (ctx->rdesc[177] != 0xef) /* Logical Max of 239 */185 ctx->retval = -EINVAL;186 187 return 0;188}189 190char _license[] SEC("license") = "GPL";191