brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · a4a4f32 Raw
296 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_HUION 0x256C11#define PID_KAMVAS_PRO_19 0x006B12#define NAME_KAMVAS_PRO_19 "HUION Huion Tablet_GT1902"13 14#define TEST_PREFIX "uhid test "15 16HID_BPF_CONFIG(17	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, VID_HUION, PID_KAMVAS_PRO_19),18);19 20bool prev_was_out_of_range;21bool in_eraser_mode;22 23/*24 * We need to amend the report descriptor for the following:25 * - the second button is reported through Secondary Tip Switch instead of Secondary Barrel Switch26 * - the third button is reported through Invert, and we need some room to report it.27 *28 */29static const __u8 fixed_rdesc[] = {30	0x05, 0x0d,                    // Usage Page (Digitizers)             031	0x09, 0x02,                    // Usage (Pen)                         232	0xa1, 0x01,                    // Collection (Application)            433	0x85, 0x0a,                    //  Report ID (10)                     634	0x09, 0x20,                    //  Usage (Stylus)                     835	0xa1, 0x01,                    //  Collection (Application)           1036	0x09, 0x42,                    //   Usage (Tip Switch)                1237	0x09, 0x44,                    //   Usage (Barrel Switch)             1438	0x09, 0x5a,                    //   Usage (Secondary Barrel Switch)   16 /* changed from Secondary Tip Switch */39	0x09, 0x3c,                    //   Usage (Invert)                    1840	0x09, 0x45,                    //   Usage (Eraser)                    2041	0x15, 0x00,                    //   Logical Minimum (0)               2242	0x25, 0x01,                    //   Logical Maximum (1)               2443	0x75, 0x01,                    //   Report Size (1)                   2644	0x95, 0x05,                    //   Report Count (5)                  28 /* changed (was 5) */45	0x81, 0x02,                    //   Input (Data,Var,Abs)              3046	0x05, 0x09,                    //   Usage Page (Button)                  /* inserted */47	0x09, 0x4a,                    //   Usage (0x4a)                         /* inserted to be translated as input usage 0x149: BTN_STYLUS3 */48	0x95, 0x01,                    //   Report Count (1)                     /* inserted */49	0x81, 0x02,                    //   Input (Data,Var,Abs)                 /* inserted */50	0x05, 0x0d,                    //   Usage Page (Digitizers)              /* inserted */51	0x09, 0x32,                    //   Usage (In Range)                  3252	0x75, 0x01,                    //   Report Size (1)                   3453	0x95, 0x01,                    //   Report Count (1)                  3654	0x81, 0x02,                    //   Input (Data,Var,Abs)              3855	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              4056	0x05, 0x01,                    //   Usage Page (Generic Desktop)      4257	0x09, 0x30,                    //   Usage (X)                         4458	0x09, 0x31,                    //   Usage (Y)                         4659	0x55, 0x0d,                    //   Unit Exponent (-3)                4860	0x65, 0x33,                    //   Unit (EnglishLinear: in³)         5061	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           5262	0x35, 0x00,                    //   Physical Minimum (0)              5563	0x46, 0x00, 0x08,              //   Physical Maximum (2048)           5764	0x75, 0x10,                    //   Report Size (16)                  6065	0x95, 0x02,                    //   Report Count (2)                  6266	0x81, 0x02,                    //   Input (Data,Var,Abs)              6467	0x05, 0x0d,                    //   Usage Page (Digitizers)           6668	0x09, 0x30,                    //   Usage (Tip Pressure)              6869	0x26, 0xff, 0x3f,              //   Logical Maximum (16383)           7070	0x75, 0x10,                    //   Report Size (16)                  7371	0x95, 0x01,                    //   Report Count (1)                  7572	0x81, 0x02,                    //   Input (Data,Var,Abs)              7773	0x09, 0x3d,                    //   Usage (X Tilt)                    7974	0x09, 0x3e,                    //   Usage (Y Tilt)                    8175	0x15, 0xa6,                    //   Logical Minimum (-90)             8376	0x25, 0x5a,                    //   Logical Maximum (90)              8577	0x75, 0x08,                    //   Report Size (8)                   8778	0x95, 0x02,                    //   Report Count (2)                  8979	0x81, 0x02,                    //   Input (Data,Var,Abs)              9180	0xc0,                          //  End Collection                     9381	0xc0,                          // End Collection                      9482	0x05, 0x0d,                    // Usage Page (Digitizers)             9583	0x09, 0x04,                    // Usage (Touch Screen)                9784	0xa1, 0x01,                    // Collection (Application)            9985	0x85, 0x04,                    //  Report ID (4)                      10186	0x09, 0x22,                    //  Usage (Finger)                     10387	0xa1, 0x02,                    //  Collection (Logical)               10588	0x05, 0x0d,                    //   Usage Page (Digitizers)           10789	0x95, 0x01,                    //   Report Count (1)                  10990	0x75, 0x06,                    //   Report Size (6)                   11191	0x09, 0x51,                    //   Usage (Contact Id)                11392	0x15, 0x00,                    //   Logical Minimum (0)               11593	0x25, 0x3f,                    //   Logical Maximum (63)              11794	0x81, 0x02,                    //   Input (Data,Var,Abs)              11995	0x09, 0x42,                    //   Usage (Tip Switch)                12196	0x25, 0x01,                    //   Logical Maximum (1)               12397	0x75, 0x01,                    //   Report Size (1)                   12598	0x95, 0x01,                    //   Report Count (1)                  12799	0x81, 0x02,                    //   Input (Data,Var,Abs)              129100	0x75, 0x01,                    //   Report Size (1)                   131101	0x95, 0x01,                    //   Report Count (1)                  133102	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              135103	0x05, 0x01,                    //   Usage Page (Generic Desktop)      137104	0x75, 0x10,                    //   Report Size (16)                  139105	0x55, 0x0e,                    //   Unit Exponent (-2)                141106	0x65, 0x11,                    //   Unit (SILinear: cm)               143107	0x09, 0x30,                    //   Usage (X)                         145108	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           147109	0x35, 0x00,                    //   Physical Minimum (0)              150110	0x46, 0x15, 0x0c,              //   Physical Maximum (3093)           152111	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         155112	0x09, 0x31,                    //   Usage (Y)                         157113	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           159114	0x46, 0xcb, 0x06,              //   Physical Maximum (1739)           162115	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         165116	0x05, 0x0d,                    //   Usage Page (Digitizers)           167117	0x09, 0x30,                    //   Usage (Tip Pressure)              169118	0x26, 0xff, 0x1f,              //   Logical Maximum (8191)            171119	0x75, 0x10,                    //   Report Size (16)                  174120	0x95, 0x01,                    //   Report Count (1)                  176121	0x81, 0x02,                    //   Input (Data,Var,Abs)              178122	0xc0,                          //  End Collection                     180123	0x05, 0x0d,                    //  Usage Page (Digitizers)            181124	0x09, 0x22,                    //  Usage (Finger)                     183125	0xa1, 0x02,                    //  Collection (Logical)               185126	0x05, 0x0d,                    //   Usage Page (Digitizers)           187127	0x95, 0x01,                    //   Report Count (1)                  189128	0x75, 0x06,                    //   Report Size (6)                   191129	0x09, 0x51,                    //   Usage (Contact Id)                193130	0x15, 0x00,                    //   Logical Minimum (0)               195131	0x25, 0x3f,                    //   Logical Maximum (63)              197132	0x81, 0x02,                    //   Input (Data,Var,Abs)              199133	0x09, 0x42,                    //   Usage (Tip Switch)                201134	0x25, 0x01,                    //   Logical Maximum (1)               203135	0x75, 0x01,                    //   Report Size (1)                   205136	0x95, 0x01,                    //   Report Count (1)                  207137	0x81, 0x02,                    //   Input (Data,Var,Abs)              209138	0x75, 0x01,                    //   Report Size (1)                   211139	0x95, 0x01,                    //   Report Count (1)                  213140	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              215141	0x05, 0x01,                    //   Usage Page (Generic Desktop)      217142	0x75, 0x10,                    //   Report Size (16)                  219143	0x55, 0x0e,                    //   Unit Exponent (-2)                221144	0x65, 0x11,                    //   Unit (SILinear: cm)               223145	0x09, 0x30,                    //   Usage (X)                         225146	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           227147	0x35, 0x00,                    //   Physical Minimum (0)              230148	0x46, 0x15, 0x0c,              //   Physical Maximum (3093)           232149	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         235150	0x09, 0x31,                    //   Usage (Y)                         237151	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           239152	0x46, 0xcb, 0x06,              //   Physical Maximum (1739)           242153	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         245154	0x05, 0x0d,                    //   Usage Page (Digitizers)           247155	0x09, 0x30,                    //   Usage (Tip Pressure)              249156	0x26, 0xff, 0x1f,              //   Logical Maximum (8191)            251157	0x75, 0x10,                    //   Report Size (16)                  254158	0x95, 0x01,                    //   Report Count (1)                  256159	0x81, 0x02,                    //   Input (Data,Var,Abs)              258160	0xc0,                          //  End Collection                     260161	0x05, 0x0d,                    //  Usage Page (Digitizers)            261162	0x09, 0x56,                    //  Usage (Scan Time)                  263163	0x55, 0x00,                    //  Unit Exponent (0)                  265164	0x65, 0x00,                    //  Unit (None)                        267165	0x27, 0xff, 0xff, 0xff, 0x7f,  //  Logical Maximum (2147483647)       269166	0x95, 0x01,                    //  Report Count (1)                   274167	0x75, 0x20,                    //  Report Size (32)                   276168	0x81, 0x02,                    //  Input (Data,Var,Abs)               278169	0x09, 0x54,                    //  Usage (Contact Count)              280170	0x25, 0x7f,                    //  Logical Maximum (127)              282171	0x95, 0x01,                    //  Report Count (1)                   284172	0x75, 0x08,                    //  Report Size (8)                    286173	0x81, 0x02,                    //  Input (Data,Var,Abs)               288174	0x75, 0x08,                    //  Report Size (8)                    290175	0x95, 0x08,                    //  Report Count (8)                   292176	0x81, 0x03,                    //  Input (Cnst,Var,Abs)               294177	0x85, 0x05,                    //  Report ID (5)                      296178	0x09, 0x55,                    //  Usage (Contact Max)                298179	0x25, 0x0a,                    //  Logical Maximum (10)               300180	0x75, 0x08,                    //  Report Size (8)                    302181	0x95, 0x01,                    //  Report Count (1)                   304182	0xb1, 0x02,                    //  Feature (Data,Var,Abs)             306183	0x06, 0x00, 0xff,              //  Usage Page (Vendor Defined Page 1) 308184	0x09, 0xc5,                    //  Usage (Vendor Usage 0xc5)          311185	0x85, 0x06,                    //  Report ID (6)                      313186	0x15, 0x00,                    //  Logical Minimum (0)                315187	0x26, 0xff, 0x00,              //  Logical Maximum (255)              317188	0x75, 0x08,                    //  Report Size (8)                    320189	0x96, 0x00, 0x01,              //  Report Count (256)                 322190	0xb1, 0x02,                    //  Feature (Data,Var,Abs)             325191	0xc0,                          // End Collection                      327192};193 194SEC(HID_BPF_RDESC_FIXUP)195int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)196{197	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);198 199	if (!data)200		return 0; /* EPERM check */201 202	__builtin_memcpy(data, fixed_rdesc, sizeof(fixed_rdesc));203 204	return sizeof(fixed_rdesc);205}206 207/*208 * This tablet reports the 3rd button through invert, but this conflict209 * with the normal eraser mode.210 * Fortunately, before entering eraser mode, (so Invert = 1),211 * the tablet always sends an out-of-proximity event.212 * So we can detect that single event and:213 * - if there was none but the invert bit was toggled: this is the214 *   third button215 * - if there was this out-of-proximity event, we are entering216 *   eraser mode, and we will until the next out-of-proximity.217 */218SEC(HID_BPF_DEVICE_EVENT)219int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)220{221	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);222 223	if (!data)224		return 0; /* EPERM check */225 226	if (data[0] != 0x0a) /* not the pen report ID */227		return 0;228 229	/* stylus is out of range */230	if (!(data[1] & 0x40)) {231		prev_was_out_of_range = true;232		in_eraser_mode = false;233		return 0;234	}235 236	/* going into eraser mode (Invert = 1) only happens after an237	 * out of range event238	 */239	if (prev_was_out_of_range && (data[1] & 0x18))240		in_eraser_mode = true;241 242	/* eraser mode works fine */243	if (in_eraser_mode)244		return 0;245 246	/* copy the Invert bit reported for the 3rd button in bit 7 */247	if (data[1] & 0x08)248		data[1] |= 0x20;249 250	/* clear Invert bit now that it was copied */251	data[1] &= 0xf7;252 253	prev_was_out_of_range = false;254 255	return 0;256}257 258HID_BPF_OPS(huion_Kamvas_pro_19) = {259	.hid_rdesc_fixup = (void *)hid_fix_rdesc_huion_kamvas_pro_19,260	.hid_device_event = (void *)kamvas_pro_19_fix_3rd_button,261};262 263SEC("syscall")264int probe(struct hid_bpf_probe_args *ctx)265{266	ctx->retval = ctx->rdesc_size != 328;267	if (ctx->retval)268		ctx->retval = -EINVAL;269 270	/* ensure the kernel isn't fixed already */271	if (ctx->rdesc[17] != 0x43) /* Secondary Tip Switch */272		ctx->retval = -EINVAL;273 274	struct hid_bpf_ctx *hctx = hid_bpf_allocate_context(ctx->hid);275 276	if (!hctx) {277		return ctx->retval = -EINVAL;278		return 0;279	}280 281	const char *name = hctx->hid->name;282 283	/* strip out TEST_PREFIX */284	if (!__builtin_memcmp(name, TEST_PREFIX, sizeof(TEST_PREFIX) - 1))285		name += sizeof(TEST_PREFIX) - 1;286 287	if (__builtin_memcmp(name, NAME_KAMVAS_PRO_19, sizeof(NAME_KAMVAS_PRO_19)))288		ctx->retval = -EINVAL;289 290	hid_bpf_release_context(hctx);291 292	return 0;293}294 295char _license[] SEC("license") = "GPL";296