File Index
Files and directories
Sign in
FILE

Thrustmaster__TCA-Yoke-Boeing.bpf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hid/bpf/progs/Thrustmaster__TCA-Yoke-Boeing.bpf.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright (c) 2024 Kumar Swarnam Iyer (kumar.s.iyer65@gmail.com)
  3 */
  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_THRUSTMASTER 0x044F
 11#define PID_TCA_YOKE_BOEING 0x0409
 12
 13HID_BPF_CONFIG(
 14	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_THRUSTMASTER, PID_TCA_YOKE_BOEING)
 15);
 16
 17/*  The original HID descriptor of the Thrustmaster TCA Yoke Boeing joystick contains
 18 *  an Input field that shows up as an axis, ABS_MISC in Linux. But it is not possible
 19 *  to assign an actual physical control to this axis as they're all taken up. There
 20 *  are 2 vendor-defined inputs where the Input type appears to be defined wrongly.
 21 *  This bpf attempts to fix this by changing the Inputs so that it doesn't show up in
 22 *  Linux at all.
 23 *  This version is the short version fix that only changes 2 fields in the descriptor
 24 *  instead of the whole report descriptor.
 25 *  For reference, this is the original report descriptor:
 26 *
 27 *  0x05, 0x01,                    // Usage Page (Generic Desktop)        0
 28 *  0x09, 0x04,                    // Usage (Joystick)                    2
 29 *  0xa1, 0x01,                    // Collection (Application)            4
 30 *  0x85, 0x01,                    //  Report ID (1)                      6
 31 *  0x09, 0x39,                    //  Usage (Hat switch)                 8
 32 *  0x15, 0x00,                    //  Logical Minimum (0)                10
 33 *  0x25, 0x07,                    //  Logical Maximum (7)                12
 34 *  0x35, 0x00,                    //  Physical Minimum (0)               14
 35 *  0x46, 0x3b, 0x01,              //  Physical Maximum (315)             16
 36 *  0x65, 0x14,                    //  Unit (EnglishRotation: deg)        19
 37 *  0x75, 0x04,                    //  Report Size (4)                    21
 38 *  0x95, 0x01,                    //  Report Count (1)                   23
 39 *  0x81, 0x42,                    //  Input (Data,Var,Abs,Null)          25
 40 *  0x65, 0x00,                    //  Unit (None)                        27
 41 *  0x05, 0x09,                    //  Usage Page (Button)                29
 42 *  0x19, 0x01,                    //  Usage Minimum (1)                  31
 43 *  0x29, 0x12,                    //  Usage Maximum (18)                 33
 44 *  0x15, 0x00,                    //  Logical Minimum (0)                35
 45 *  0x25, 0x01,                    //  Logical Maximum (1)                37
 46 *  0x75, 0x01,                    //  Report Size (1)                    39
 47 *  0x95, 0x12,                    //  Report Count (18)                  41
 48 *  0x81, 0x02,                    //  Input (Data,Var,Abs)               43
 49 *  0x95, 0x02,                    //  Report Count (2)                   45
 50 *  0x81, 0x03,                    //  Input (Cnst,Var,Abs)               47
 51 *  0x05, 0x01,                    //  Usage Page (Generic Desktop)       49
 52 *  0x09, 0x31,                    //  Usage (Y)                          51
 53 *  0x09, 0x30,                    //  Usage (X)                          53
 54 *  0x09, 0x32,                    //  Usage (Z)                          55
 55 *  0x09, 0x34,                    //  Usage (Ry)                         57
 56 *  0x09, 0x33,                    //  Usage (Rx)                         59
 57 *  0x09, 0x35,                    //  Usage (Rz)                         61
 58 *  0x15, 0x00,                    //  Logical Minimum (0)                63
 59 *  0x27, 0xff, 0xff, 0x00, 0x00,  //  Logical Maximum (65535)            65
 60 *  0x75, 0x10,                    //  Report Size (16)                   70
 61 *  0x95, 0x06,                    //  Report Count (6)                   72
 62 *  0x81, 0x02,                    //  Input (Data,Var,Abs)               74
 63 *  0x06, 0xf0, 0xff,              //  Usage Page (Vendor Usage Page 0xfff0) 76
 64 *  0x09, 0x59,                    //  Usage (Vendor Usage 0x59)          79
 65 *  0x15, 0x00,                    //  Logical Minimum (0)                81
 66 *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              83
 67 *  0x75, 0x08,                    //  Report Size (8)                    86
 68 *  0x95, 0x01,                    //  Report Count (1)                   88
 69 *  0x81, 0x02,                    //  Input (Data,Var,Abs)               90 --> Needs to be changed
 70 *  0x09, 0x51,                    //  Usage (Vendor Usage 0x51)          92
 71 *  0x15, 0x00,                    //  Logical Minimum (0)                94
 72 *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              96
 73 *  0x75, 0x08,                    //  Report Size (8)                    99
 74 *  0x95, 0x20,                    //  Report Count (32)                  101 --> Needs to be changed
 75 *  0x81, 0x02,                    //  Input (Data,Var,Abs)               103
 76 *  0x09, 0x50,                    //  Usage (Vendor Usage 0x50)          105
 77 *  0x15, 0x00,                    //  Logical Minimum (0)                107
 78 *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              109
 79 *  0x75, 0x08,                    //  Report Size (8)                    112
 80 *  0x95, 0x0f,                    //  Report Count (15)                  114
 81 *  0x81, 0x03,                    //  Input (Cnst,Var,Abs)               116
 82 *  0x09, 0x47,                    //  Usage (Vendor Usage 0x47)          118
 83 *  0x85, 0xf2,                    //  Report ID (242)                    120
 84 *  0x15, 0x00,                    //  Logical Minimum (0)                122
 85 *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              124
 86 *  0x75, 0x08,                    //  Report Size (8)                    127
 87 *  0x95, 0x3f,                    //  Report Count (63)                  129
 88 *  0xb1, 0x02,                    //  Feature (Data,Var,Abs)             131
 89 *  0x09, 0x48,                    //  Usage (Vendor Usage 0x48)          133
 90 *  0x85, 0xf3,                    //  Report ID (243)                    135
 91 *  0x15, 0x00,                    //  Logical Minimum (0)                137
 92 *  0x26, 0xff, 0x00,              //  Logical Maximum (255)              139
 93 *  0x75, 0x08,                    //  Report Size (8)                    142
 94 *  0x95, 0x3f,                    //  Report Count (63)                  144
 95 *  0xb1, 0x02,                    //  Feature (Data,Var,Abs)             146
 96 *  0xc0,                          // End Collection                      148
 97 */
 98
 99SEC(HID_BPF_RDESC_FIXUP)
100int BPF_PROG(hid_fix_rdesc_tca_yoke, struct hid_bpf_ctx *hctx)
101{
102	const int expected_length = 148;
103
104	if (hctx->size != expected_length)
105		return 0;
106
107	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
108
109	if (!data)
110		return 0; /* EPERM */
111
112	/* Safety check, our probe() should take care of this though */
113	if (data[1] != 0x01 /* Generic Desktop */ || data[3] != 0x04 /* Joystick */)
114		return 0;
115
116	/* The report descriptor sets incorrect Input items in 2 places, resulting in a
117	 * non-existing axis showing up.
118	 * This change sets the correct Input which prevents the axis from showing up in Linux.
119	 */
120
121	if (data[90] == 0x81 && /* Input */
122	    data[103] == 0x81) { /* Input */
123		data[91] = 0x03; /* Input set to 0x03 Constant, Variable Absolute */
124		data[104] = 0x03; /* Input set to 0X03 Constant, Variable Absolute */
125	}
126
127	return 0;
128}
129
130HID_BPF_OPS(tca_yoke) = {
131	.hid_rdesc_fixup = (void *)hid_fix_rdesc_tca_yoke,
132};
133
134SEC("syscall")
135int probe(struct hid_bpf_probe_args *ctx)
136{
137	/* ensure the kernel isn't fixed already */
138	if (ctx->rdesc[91] != 0x02) /* Input for 0x59 Usage type has changed */
139		ctx->retval = -EINVAL;
140
141	return 0;
142}
143
144char _license[] SEC("license") = "GPL";
~/ Read-only file preview.