Files
Centos-kernel-stream-10/drivers/hid/bpf/progs/Logitech__SpaceNavigator.bpf.c
T
Benjamin Tissoires 04369ba7ce HID: bpf: Add fixup for Logitech SpaceNavigator variants
JIRA: https://issues.redhat.com/browse/RHEL-170872
Upstream Status: since v6.19

commit 029dff1c31c488e85c666d5e7e992700cd57462b
Author: Benjamin Tissoires <bentiss@kernel.org>
Date:   Tue Nov 18 18:16:25 2025 +0100

    HID: bpf: Add fixup for Logitech SpaceNavigator variants

    The 3Dconnexion SpaceNavigator HID report descriptor declares its axis
    data to be "relative" when it is actually "absolute".  This quirk was
    addressed in the kernel in 2.6.33, but some SpaceNavigator variants have
    a slightly different report descriptor whose axis input items are at
    different offsets than those assumed by the kernel fixup.

    Add a BPF fixup to handle both sets of offsets for known SpaceNavigator
    variants if the descriptor has not already been fixed by the kernel.

    Signed-off-by: Curran Muhlberger <curran@cs.cornell.edu>
    Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/181
    Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
    Signed-off-by: Jiri Kosina <jkosina@suse.com>

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
2026-06-29 15:43:17 +02:00

87 lines
2.5 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2025 Curran Muhlberger
*/
#include "vmlinux.h"
#include "hid_bpf.h"
#include "hid_bpf_helpers.h"
#include <bpf/bpf_tracing.h>
#define VID_LOGITECH 0x046D
#define PID_SPACENAVIGATOR 0xC626
HID_BPF_CONFIG(
HID_DEVICE(BUS_USB, HID_GROUP_ANY, VID_LOGITECH, PID_SPACENAVIGATOR)
);
/*
* The 3Dconnexion SpaceNavigator 3D Mouse is a multi-axis controller with 6
* axes (grouped as X,Y,Z and Rx,Ry,Rz). Axis data is absolute, but the report
* descriptor erroneously declares it to be relative. We fix the report
* descriptor to mark both axis collections as absolute.
*
* The kernel attempted to fix this in commit 24985cf68612 (HID: support
* Logitech/3DConnexion SpaceTraveler and SpaceNavigator), but the descriptor
* data offsets are incorrect for at least some SpaceNavigator units.
*/
SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
if (!data)
return 0; /* EPERM check */
/* Offset of Input item in X,Y,Z and Rx,Ry,Rz collections for all known
* firmware variants.
* - 2009 model: X,Y,Z @ 32-33, Rx,Ry,Rz @ 49-50 (fixup originally
* applied in kernel)
* - 2016 model (size==228): X,Y,Z @ 36-37, Rx,Ry,Rz @ 53-54
*
* The descriptor size of the 2009 model is not known, and there is evidence
* for at least two other variants (with sizes 202 & 217) besides the 2016
* model, so we try all known offsets regardless of descriptor size.
*/
const u8 offsets[] = {32, 36, 49, 53};
for (size_t idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
u8 offset = offsets[idx];
/* if Input (Data,Var,Rel) , make it Input (Data,Var,Abs) */
if (data[offset] == 0x81 && data[offset + 1] == 0x06)
data[offset + 1] = 0x02;
}
return 0;
}
HID_BPF_OPS(logitech_spacenavigator) = {
.hid_rdesc_fixup = (void *)hid_fix_rdesc,
};
SEC("syscall")
int probe(struct hid_bpf_probe_args *ctx)
{
/* Ensure report descriptor size matches one of the known variants. */
if (ctx->rdesc_size != 202 &&
ctx->rdesc_size != 217 &&
ctx->rdesc_size != 228) {
ctx->retval = -EINVAL;
return 0;
}
/* Check whether the kernel has already applied the fix. */
if ((ctx->rdesc[32] == 0x81 && ctx->rdesc[33] == 0x02 &&
ctx->rdesc[49] == 0x81 && ctx->rdesc[50] == 0x02) ||
(ctx->rdesc[36] == 0x81 && ctx->rdesc[37] == 0x02 &&
ctx->rdesc[53] == 0x81 && ctx->rdesc[54] == 0x02))
ctx->retval = -EINVAL;
else
ctx->retval = 0;
return 0;
}
char _license[] SEC("license") = "GPL";