* [RFC PATCH 5/6] Input: Realign rest of the HID_UP_BUTTON cases
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
In-Reply-To: <20260104213132.163904-1-tomasz.pakula.oficjalny@gmail.com>
The switch statement here had too much indentation.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/hid-input.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 1c11077b1577..9542829de234 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -770,22 +770,22 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
code = KEY_RESERVED;
break;
case HID_GD_GAMEPAD:
- if (code <= 0xf)
- code += BTN_GAMEPAD;
- else
- code += BTN_TRIGGER_HAPPY - 0x10;
- break;
+ if (code <= 0xf)
+ code += BTN_GAMEPAD;
+ else
+ code += BTN_TRIGGER_HAPPY - 0x10;
+ break;
case HID_CP_CONSUMER_CONTROL:
- if (hidinput_field_in_collection(device, field,
- HID_COLLECTION_NAMED_ARRAY,
- HID_CP_PROGRAMMABLEBUTTONS)) {
- if (code <= 0x1d)
- code += KEY_MACRO1;
- else
- code += BTN_TRIGGER_HAPPY - 0x1e;
- break;
- }
- fallthrough;
+ if (hidinput_field_in_collection(device, field,
+ HID_COLLECTION_NAMED_ARRAY,
+ HID_CP_PROGRAMMABLEBUTTONS)) {
+ if (code <= 0x1d)
+ code += KEY_MACRO1;
+ else
+ code += BTN_TRIGGER_HAPPY - 0x1e;
+ break;
+ }
+ fallthrough;
default:
switch (field->physical) {
case HID_GD_MOUSE:
--
2.52.0
^ permalink raw reply related
* [RFC PATCH 4/6] Input: Assign EV_BTN event to HID Joysticks
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
In-Reply-To: <20260104213132.163904-1-tomasz.pakula.oficjalny@gmail.com>
Joysticks will now fire EV_BTN for every of their buttons, even buttons
that were previously ignored because they were cut off by KEY_MAX. This
in turns enables joysticks to finally report buttons above 80 which was
the previous limitation.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/hid-input.c | 27 +++++++++++++++++++++------
include/linux/input.h | 2 ++
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 900a6fc9813e..1c11077b1577 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -760,11 +760,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_GD_MOUSE:
case HID_GD_POINTER: code += BTN_MOUSE; break;
case HID_GD_JOYSTICK:
- if (code <= 0xf)
- code += BTN_JOYSTICK;
- else
- code += BTN_TRIGGER_HAPPY - 0x10;
- break;
+ if (input->button_count >= INPUT_MAX_BUTTONS)
+ goto ignore;
+
+ code += BTN_JOYSTICK;
+ if (code > BTN_DEAD)
+ code += BTN_TRIGGER_HAPPY - BTN_DEAD - 1;
+ if (code > KEY_MAX)
+ code = KEY_RESERVED;
+ break;
case HID_GD_GAMEPAD:
if (code <= 0xf)
code += BTN_GAMEPAD;
@@ -1379,7 +1383,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
set_bit(usage->type, input->evbit);
-
/*
* This part is *really* controversial:
* - HID aims at being generic so we should do our best to export
@@ -1390,12 +1393,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
* *_MISC+N to overwrite a legitimate even, which confuses userspace
* (for instance ABS_MISC + 7 is ABS_MT_SLOT, which has a different
* processing)
+ * - Joysticks can have arbitrary number of buttons without defined
+ * usages. Buttons that extend beyond KEY_MAX are assigned to
+ * KEY_RESERVED thus deduplication must be disabled for them.
*
* If devices still want to use this (at their own risk), they will
* have to use the quirk HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE, but
* the default should be a reliable mapping.
*/
while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
+ if (field->application == HID_GD_JOYSTICK && usage->code == KEY_RESERVED)
+ break;
+
if (device->quirks & HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE) {
usage->code = find_next_zero_bit(bit,
max + 1,
@@ -1455,6 +1464,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (usage->type == EV_KEY) {
set_bit(EV_MSC, input->evbit);
set_bit(MSC_SCAN, input->mscbit);
+
+ if (field->application == HID_GD_JOYSTICK &&
+ (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
+ set_bit(EV_BTN, input->evbit);
+ ++input->button_count;
+ }
}
return;
diff --git a/include/linux/input.h b/include/linux/input.h
index f6389de4a4d1..7f39c663fa85 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -214,6 +214,8 @@ struct input_dev {
};
#define to_input_dev(d) container_of(d, struct input_dev, dev)
+#define INPUT_MAX_BUTTONS 2048 /* A sane limit of supported device buttons */
+
/*
* Verify that we are in sync with input_device_id mod_devicetable.h #defines
*/
--
2.52.0
^ permalink raw reply related
* [RFC PATCH 3/6] Input: Fire EV_BTN if found in ev_bit
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
In-Reply-To: <20260104213132.163904-1-tomasz.pakula.oficjalny@gmail.com>
Passes EV_BTN through to handlers and allows reacting to this event by
clients.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/hid/hid-input.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2bbb645c2ff4..900a6fc9813e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1673,7 +1673,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
switch (usage->type) {
case EV_KEY:
- if (usage->code == 0) /* Key 0 is "unassigned", not KEY_UNKNOWN */
+ /* Key 0 is "unassigned", not KEY_UNKNOWN */
+ if (usage->code == 0 && !test_bit(EV_BTN, input->evbit))
return;
break;
@@ -1723,10 +1724,19 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
value == field->value[usage->usage_index])
return;
- /* report the usage code as scancode if the key status has changed */
- if (usage->type == EV_KEY &&
- (!test_bit(usage->code, input->key)) == value)
- input_event(input, EV_MSC, MSC_SCAN, usage->hid);
+
+ if (usage->type == EV_KEY) {
+ /* Send out EV_BTN with button number (starts at 1) */
+ if (test_bit(EV_BTN, input->evbit))
+ input_event(input, EV_BTN, usage->hid & HID_USAGE, value);
+
+ if (usage->code == 0)
+ return;
+
+ /* report usage code as scancode if the status has changed */
+ if ((!test_bit(usage->code, input->key)) == value)
+ input_event(input, EV_MSC, MSC_SCAN, usage->hid);
+ }
input_event(input, usage->type, usage->code, value);
--
2.52.0
^ permalink raw reply related
* [RFC PATCH 2/6] Input: Add info about EV_BTN
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
In-Reply-To: <20260104213132.163904-1-tomasz.pakula.oficjalny@gmail.com>
Add necessary bits to modalias etc. Store the number of buttons.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
drivers/input/input.c | 10 ++++++++++
include/linux/input.h | 2 ++
2 files changed, 12 insertions(+)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a500e1e276c2..e926327443bb 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -258,6 +258,10 @@ static int input_get_disposition(struct input_dev *dev,
}
break;
+ case EV_BTN:
+ disposition = INPUT_PASS_TO_HANDLERS;
+ break;
+
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value);
@@ -1124,6 +1128,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
if (test_bit(EV_SW, dev->evbit))
input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+ if (test_bit(EV_BTN, dev->evbit))
+ seq_printf(seq, "I: BTN=%u\n", dev->button_count);
seq_putc(seq, '\n');
@@ -1347,6 +1353,7 @@ static int input_print_modalias_parts(char *buf, int size, int full_len,
'f', id->ffbit, 0, FF_MAX);
len += input_print_modalias_bits(buf + len, size - len,
'w', id->swbit, 0, SW_MAX);
+ len += snprintf(buf + len, size - len, "t%u", id->button_count);
return len;
}
@@ -1679,6 +1686,8 @@ static int input_dev_uevent(const struct device *device, struct kobj_uevent_env
INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+ if (test_bit(EV_BTN, dev->evbit))
+ INPUT_ADD_HOTPLUG_VAR("BTN=%u", dev->button_count);
INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
@@ -2113,6 +2122,7 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
break;
case EV_PWR:
+ case EV_BTN:
/* do nothing */
break;
diff --git a/include/linux/input.h b/include/linux/input.h
index 7d7cb0593a63..f6389de4a4d1 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -59,6 +59,7 @@ enum input_clock_type {
* @sndbit: bitmap of sound effects supported by the device
* @ffbit: bitmap of force feedback effects supported by the device
* @swbit: bitmap of switches present on the device
+ * @button_count: number of generic buttons present on the device.
* @hint_events_per_packet: average number of events generated by the
* device in a packet (between EV_SYN/SYN_REPORT events). Used by
* event handlers to estimate size of the buffer needed to hold
@@ -152,6 +153,7 @@ struct input_dev {
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
+ unsigned int button_count;
unsigned int hint_events_per_packet;
unsigned int keycodemax;
--
2.52.0
^ permalink raw reply related
* [RFC PATCH 1/6] Input: Introduce EV_BTN event for generic buttons
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
In-Reply-To: <20260104213132.163904-1-tomasz.pakula.oficjalny@gmail.com>
This will be used to fire generic button events that only transmit
button number and it's value, not related to any defined usage.
Made for HID joysticks but could be adopted by other devices.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
Documentation/input/event-codes.rst | 5 +++++
include/uapi/linux/input-event-codes.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/Documentation/input/event-codes.rst b/Documentation/input/event-codes.rst
index 4424cbff251f..c387eaa63dfb 100644
--- a/Documentation/input/event-codes.rst
+++ b/Documentation/input/event-codes.rst
@@ -59,6 +59,11 @@ Codes section for details on valid codes for each type.
- Used to describe binary state input switches.
+* EV_BTN:
+
+ - Used to describe state changes generic, numbered buttons without defined
+ usages.
+
* EV_LED:
- Used to turn LEDs on devices on and off.
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 30f3c9eaafaa..1c853c37b58a 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -42,6 +42,7 @@
#define EV_ABS 0x03
#define EV_MSC 0x04
#define EV_SW 0x05
+#define EV_BTN 0x06
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
--
2.52.0
^ permalink raw reply related
* [RFC PATCH 0/6] Input: New EV_BTN event for generic buttons
From: Tomasz Pakuła @ 2026-01-04 21:31 UTC (permalink / raw)
To: dmitry.torokhov, corbet, jikos, bentiss
Cc: linux-input, linux-kernel, linux-doc, vi, linux-kernel,
peter.hutterer
This patch series adds EV_BTN and it's handling to the input system. It's main
focus is to add a simple event for generic buttons, not relying on defined
usages and meanings.
Joysticks unlike keyboards, mice and even gamepads (though that's debatable)
define arbitrary number of buttons that don't mean anything. They can be used
in any kind of software, but mainly games, by assigning them manually to
functions. Some games even carry default presets for devices based on their USB
VID:PID pairs.
The more important issue that this is trying to solve is the longstanding
problem of limited button support in Linux. The use for arbitrary number of
buttons wasn't considered some 20 years ago because Linux wasn't a good platform
for gaming. First, Joystick and Gamepad ranges were limited to 16 buttons, later
extended by 40 additional usages in the TRIGGER_HAPPY range. By allowing the
usages to be incremented up to KEY_MAX, Joysticks were able to expose up to 80
buttons for the past 15 years or so.
Many simracing, simflight etc. devices actually expose way more then that. 128
is a pretty common number with even more in the wild. Usually the numbers get so
big to support things like positional rotary switches as one such rotary can
have 12+ positions. My Moza GS V2P wheel has 5 such rotaries and that's not
counting other buttons.
Doing something about this limit was brought up maaany times in the past:
https://forums.x-plane.org/forums/topic/299033-xp12-linux-winwing-orion-2-throttle-has-too-many-buttons/?page=1
https://forum.falcon-bms.com/topic/26403/solved-winwing-orion-2-on-linux-only-80-buttons-detected
https://lore.kernel.org/linux-input/CACa7zynMpa3BOJUW=s_Tj1TwH5txDQOuta5Fph45PYhDOtQQ3g@mail.gmail.com/
https://lore.kernel.org/linux-input/20200710065112.18286-1-cpuwolf@gmail.com/#r
https://lore.kernel.org/linux-input/20240802201001.406898-1-tomasz.pakula.oficjalny@gmail.com/
https://lore.kernel.org/linux-input/20250201113906.769162-11-tomasz.pakula.oficjalny@gmail.com/
https://lore.kernel.org/linux-input/20251119163844.1343-1-Hunter.Moore@garmin.com/
https://lore.kernel.org/linux-input/20251220194100.GA12646@altimeter-info/
https://lore.kernel.org/linux-input/665df7c9-0d32-4ecd-9f4d-fff67deb5878@endrift.com/
But some considerations:
1. Usages have their actual meanings and we shouldn't use them willy-nilly to add
more buttons, even if that approach works with naive approaches use by SDL and
Wine alike.
2. Extending the KEY_MAX will cause additional issues when it comes to bitmask
sizes, mapping usages and reading them afterward. Basically, we're moving the
goalpost somewhere, but a device that would define 1024 buttons would break
things again.
I must give HUGE thanks to Dmitry for forcing this into my head to a point where
I actually understood the whole issue.
Thus, I thought up of a best, long-term solution to this problem. I do think
EV_BTN should be a first-class event so it can be as easy to handle as possible.
If there's a need, it could be hooked up for Gamepads as well as HID gamepads do
the same thing and only expose raw buttons without specific usages. The usages
are a best guess when handling generic ones and only custom drivers can actually
assign proper buttons like BTN_A, THUMBL etc.
In the future, the Joystick usages could be completely removed and joysticks
could rely ONLY on the new event. For now, the old way is kept to not break
compatibility.
I'm eagerly waiting for comments, recommendations and critique. Currently, there
isn't a way to poll states of all buttons like with EVIOCGKEY but I'm not sure
if it's needed? I added INPUT_MAX_KEYS just for some sane limits BUT I don't see
a real use for it. Instead of this define, we could just use U16_MAX. 65k of
buttons ought to be enough for ANYBODY :D
Companion changes to consumers that already show the working state of this patch series:
Wine: https://gitlab.winehq.org/wine/wine/-/merge_requests/9853
SDL: https://github.com/libsdl-org/SDL/pull/14758
evtest: https://gitlab.freedesktop.org/libevdev/evtest/-/merge_requests/25
Tested with my Moza Racing R9 and Moza Universal Hub (both expose 128 usable
buttons). hid-universal-pidff driver was disabled for testing as it contains
usage range hack.
Sneak peek from updated evtest:
Event: time 1767559522.509446, type 6 (EV_BTN), button 12, value 1
Event: time 1767559522.509446, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000c
Event: time 1767559522.509446, type 1 (EV_KEY), code 299 (BTN_BASE6), value 1
Event: time 1767559522.509446, -------------- SYN_REPORT ------------
Event: time 1767559522.656447, type 6 (EV_BTN), button 12, value 0
Event: time 1767559522.656447, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000c
Event: time 1767559522.656447, type 1 (EV_KEY), code 299 (BTN_BASE6), value 0
Event: time 1767559522.656447, -------------- SYN_REPORT ------------
Event: time 1767559523.737498, type 6 (EV_BTN), button 112, value 1
Event: time 1767559523.737498, -------------- SYN_REPORT ------------
Event: time 1767559523.807477, type 6 (EV_BTN), button 112, value 0
Event: time 1767559523.807477, -------------- SYN_REPORT ------------
Tomasz Pakuła (6):
Input: Introduce EV_BTN event for generic buttons
Input: Add info about EV_BTN
Input: Fire EV_BTN if found in ev_bit
Input: Assign EV_BTN event to HID Joysticks
Input: Realign rest of the HID_UP_BUTTON cases
Input: Add EVIOCGBTNCNT
Documentation/input/event-codes.rst | 5 ++
drivers/hid/hid-input.c | 77 +++++++++++++++++---------
drivers/input/evdev.c | 5 ++
drivers/input/input.c | 10 ++++
include/linux/input.h | 4 ++
include/uapi/linux/input-event-codes.h | 1 +
include/uapi/linux/input.h | 1 +
7 files changed, 77 insertions(+), 26 deletions(-)
--
2.52.0
^ permalink raw reply
* [PATCH] drivers/hid: add HID++ support for Logitech MX Anywhere 3S
From: Dennis Marttinen @ 2026-01-04 13:00 UTC (permalink / raw)
To: Filipe Lains, Bastien Nocera, Jiri Kosina, Benjamin Tissoires,
linux-input, linux-kernel
Cc: Dennis Marttinen
I've acquired a Logitech MX Anywhere 3S mouse, which supports HID++ over
Bluetooth. Adding its PID 0xb037 to the allowlist enables the additional
features, such as high-resolution scrolling. Tested working across multiple
machines, with a mix of Intel and Mediatek Bluetooth chips.
Signed-off-by: Dennis Marttinen <twelho@welho.tech>
---
drivers/hid/hid-logitech-hidpp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index d5011a5d08902..e871f1729d4b3 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -4662,6 +4662,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb025) },
{ /* MX Master 3S mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) },
+ { /* MX Anywhere 3S mouse over Bluetooth */
+ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb037) },
{ /* MX Anywhere 3SB mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) },
{}
--
2.52.0
^ permalink raw reply related
* Re: [PATCH] HID: input: Increase maximum number of joystick buttons
From: Ivan Gorinov @ 2026-01-04 0:48 UTC (permalink / raw)
To: tomasz.pakula.oficjalny; +Cc: Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <aa40f6010c721863c09673fc8801e0a382619d89.camel@gmail.com>
On Sat, Jan 03, 2026 at 08:26:55PM +0100, tomasz.pakula.oficjalny@gmail.com wrote:
> On Sat, 2025-12-20 at 19:41 +0000, Ivan Gorinov wrote:
> > This patch increases the limit from 80 to 112 key codes.
> >
> > If a joystick has 80 or fewer buttons, mapping stays the same.
> >
> > If a joystick has more than 80 buttons:
> >
> > Map buttons [ 0 .. 15 ] to key codes starting with BTN_JOYSTICK;
> > Map buttons [ 16 .. 47 ] to key codes starting with KEY_MACRO1;
> > Map buttons [ 48 .. 111 ] to key codes starting with BTN_TRIGGER_HAPPY.
> >
>
> As stated previously by Dmitry when I tried to increase the KEY_MAX for
> the same reason, the defined usages have their place and shouldn't be
> misused. I finally understood that and I have to say that this is just
> more confusing and a dirty hack, certainly used by some drivers because
> it still works with SDL and Wine (they only care about the usage index).
>
> I'm working on a proper solution with a new event type that will only
> send button number (starting from 1 as does plain HID) and it's value.
>
> This will support up to 65535 (u16) buttons and should be enough for
> years to come :D I'll make sure to CC you when I'll send RFC.
Thank you! I learned how to map more than 80 buttons by overriding function
hid_driver.input_mapping from your contribution to JacKeTUs/universal-pdiff
and used the same idea in my recent changes in the hid-winwing module.
Good luck in your work on new event type!
I will test your changes with my Orion2/TGRIP-18 combo.
Meanwhile, this patch could allow existing software (for example, X-Plane 12)
to work with more input devices without any changes in userspace.
^ permalink raw reply
* Re: [PATCH] HID: input: Increase maximum number of joystick buttons
From: tomasz.pakula.oficjalny @ 2026-01-03 19:26 UTC (permalink / raw)
To: Ivan Gorinov, Jiri Kosina; +Cc: linux-input, linux-kernel
In-Reply-To: <20251220194100.GA12646@altimeter-info>
On Sat, 2025-12-20 at 19:41 +0000, Ivan Gorinov wrote:
> This patch increases the limit from 80 to 112 key codes.
>
> If a joystick has 80 or fewer buttons, mapping stays the same.
>
> If a joystick has more than 80 buttons:
>
> Map buttons [ 0 .. 15 ] to key codes starting with BTN_JOYSTICK;
> Map buttons [ 16 .. 47 ] to key codes starting with KEY_MACRO1;
> Map buttons [ 48 .. 111 ] to key codes starting with BTN_TRIGGER_HAPPY.
>
> Signed-off-by: Ivan Gorinov <linux-kernel@altimeter.info>
> ---
> drivers/hid/hid-input.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 2633fcd8f910..c6159f96de04 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -763,7 +763,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
> if (code <= 0xf)
> code += BTN_JOYSTICK;
> else
> - code += BTN_TRIGGER_HAPPY - 0x10;
> + if (field->maxusage <= 80)
> + code += BTN_TRIGGER_HAPPY - 0x10;
> + else
> + if (code <= 0x2f)
> + code += KEY_MACRO1 - 0x10;
> + else
> + code += BTN_TRIGGER_HAPPY - 0x30;
> break;
> case HID_GD_GAMEPAD:
> if (code <= 0xf)
As stated previously by Dmitry when I tried to increase the KEY_MAX for
the same reason, the defined usages have their place and shouldn't be
misused. I finally understood that and I have to say that this is just
more confusing and a dirty hack, certainly used by some drivers because
it still works with SDL and Wine (they only care about the usage index).
I'm working on a proper solution with a new event type that will only
send button number (starting from 1 as does plain HID) and it's value.
This will support up to 65535 (u16) buttons and should be enough for
years to come :D I'll make sure to CC you when I'll send RFC.
^ permalink raw reply
* Re: [PATCH 0/4] PM: Hibernate: Add hibernation cancellation support
From: Pavel Machek @ 2026-01-02 22:40 UTC (permalink / raw)
To: Muhammad Usama Anjum
Cc: Rafael J. Wysocki, Len Brown, Greg Kroah-Hartman,
Danilo Krummrich, Dmitry Torokhov, Thomas Gleixner,
Peter Zijlstra, linux-acpi, linux-kernel, linux-pm, linux-input,
kernel, superm1
In-Reply-To: <20251107184438.1328717-1-usama.anjum@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 641 bytes --]
Hi!
> On a normal laptop/PC, the hibernation takes 15-20 seconds which is
> considerable time. Once hibernation is triggered from command line or by
> some GUI option, the hibernation cannot be cancelled until completed.
> Its not a blocker, but poor user experience.
In-kernel hibernation is basic and simple. It is not great, and not
designed to be great.
You can do fancy progress bars, cancellations and probably better
encryption in userspace.
Documentation/power/swsusp.rst
Best regards,
Pavel
--
I don't work for Nazis and criminals, and neither should you.
Boycott Putin, Trump, Netanyahu and Musk!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply
* [PATCH] HID: sony: add support for Rock Band 4 PS4 and PS5 guitars
From: Rosalie Wanders @ 2026-01-02 21:12 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: Rosalie Wanders, linux-input, linux-kernel
This commit adds support for the PDP RiffMaster and the CRKD Gibson SG
in both their PS4 and PS5 modes.
These devices aren't mapped correctly without these changes, they also
lack support for their whammy and tilt functionality which this patch
adds support for by binding them to the left and right triggers.
Signed-off-by: Rosalie Wanders <rosalie@mailbox.org>
---
drivers/hid/Kconfig | 4 +-
drivers/hid/hid-ids.h | 8 +++
drivers/hid/hid-sony.c | 119 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 920a64b66b25..932e4110bb38 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1084,7 +1084,7 @@ config HID_SIGMAMICRO
- Rapoo V500
config HID_SONY
- tristate "Sony PS2/3/4 accessories"
+ tristate "Sony PS2/3/4/5 accessories"
depends on USB_HID
depends on NEW_LEDS
depends on LEDS_CLASS
@@ -1094,12 +1094,12 @@ config HID_SONY
Support for
* Sony PS3 6-axis controllers
- * Sony PS4 DualShock 4 controllers
* Buzz controllers
* Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
* Guitar Hero Live PS3, Wii U and PS4 guitar dongles
* Guitar Hero PS3 and PC guitar dongles
+ * Rock Band 4 PS4 and PS5 guitars
config SONY_FF
bool "Sony PS2/3/4 accessories force feedback support"
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d31711f1aaec..d95768c8fe06 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -363,6 +363,10 @@
#define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
#define USB_DEVICE_ID_CREATIVE_SB0540 0x3100
+#define USB_VENDOR_ID_CRKD 0x3651
+#define USB_DEVICE_ID_CRKD_PS4_GIBSON_SG 0x1500
+#define USB_DEVICE_ID_CRKD_PS5_GIBSON_SG 0x1600
+
#define USB_VENDOR_ID_CVTOUCH 0x1ff7
#define USB_DEVICE_ID_CVTOUCH_SCREEN 0x0013
@@ -1145,6 +1149,10 @@
#define USB_VENDOR_ID_POWERCOM 0x0d9f
#define USB_DEVICE_ID_POWERCOM_UPS 0x0002
+#define USB_VENDOR_ID_PDP 0x0e6F
+#define USB_DEVICE_ID_PDP_PS4_RIFFMASTER 0x024a
+#define USB_DEVICE_ID_PDP_PS5_RIFFMASTER 0x0249
+
#define USB_VENDOR_ID_PRODIGE 0x05af
#define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index b966e4044238..e2f17a99fa42 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -14,6 +14,7 @@
* Copyright (c) 2020-2021 Pascal Giard <pascal.giard@etsmtl.ca>
* Copyright (c) 2020 Sanjay Govind <sanjay.govind9@gmail.com>
* Copyright (c) 2021 Daniel Nguyen <daniel.nguyen.1@ens.etsmtl.ca>
+ * Copyright (c) 2026 Rosalie Wanders <rosalie@mailbox.org>
*/
/*
@@ -61,6 +62,8 @@
#define GH_GUITAR_CONTROLLER BIT(14)
#define GHL_GUITAR_PS3WIIU BIT(15)
#define GHL_GUITAR_PS4 BIT(16)
+#define RB4_GUITAR_PS4 BIT(17)
+#define RB4_GUITAR_PS5 BIT(18)
#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -418,6 +421,27 @@ static const unsigned int sixaxis_keymap[] = {
[0x11] = BTN_MODE, /* PS */
};
+static const unsigned int rb4_absmap[] = {
+ [0x30] = ABS_X,
+ [0x31] = ABS_Y,
+};
+
+static const unsigned int rb4_keymap[] = {
+ [0x1] = BTN_WEST, /* Square */
+ [0x2] = BTN_SOUTH, /* Cross */
+ [0x3] = BTN_EAST, /* Circle */
+ [0x4] = BTN_NORTH, /* Triangle */
+ [0x5] = BTN_TL, /* L1 */
+ [0x6] = BTN_TR, /* R1 */
+ [0x7] = BTN_TL2, /* L2 */
+ [0x8] = BTN_TR2, /* R2 */
+ [0x9] = BTN_SELECT, /* Share */
+ [0xa] = BTN_START, /* Options */
+ [0xb] = BTN_THUMBL, /* L3 */
+ [0xc] = BTN_THUMBR, /* R3 */
+ [0xd] = BTN_MODE, /* PS */
+};
+
static enum power_supply_property sony_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
@@ -484,6 +508,7 @@ struct sony_sc {
spinlock_t lock;
struct list_head list_node;
struct hid_device *hdev;
+ struct input_dev *input_dev;
struct input_dev *touchpad;
struct input_dev *sensor_dev;
struct led_classdev *leds[MAX_LEDS];
@@ -584,7 +609,7 @@ static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev,
return 0;
}
-static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
+static int gh_guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
@@ -599,6 +624,38 @@ static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
+static int rb4_guitar_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
+ unsigned int key = usage->hid & HID_USAGE;
+
+ if (key >= ARRAY_SIZE(rb4_keymap))
+ return 0;
+
+ key = rb4_keymap[key];
+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+ return 1;
+ } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
+ unsigned int abs = usage->hid & HID_USAGE;
+
+ /* Let the HID parser deal with the HAT. */
+ if (usage->hid == HID_GD_HATSWITCH)
+ return 0;
+
+ if (abs >= ARRAY_SIZE(rb4_absmap))
+ return 0;
+
+ abs = rb4_absmap[abs];
+ hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
+ return 1;
+ }
+
+ return 0;
+}
+
static const u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
unsigned int *rsize)
{
@@ -915,6 +972,40 @@ static void nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size)
input_sync(sc->touchpad);
}
+static void rb4_ps4_guitar_parse_report(struct sony_sc *sc, u8 *rd, int size)
+{
+ /*
+ * Rock Band 4 PS4 guitars have whammy and
+ * tilt functionality, they're located at
+ * byte 44 and 45 respectively.
+ *
+ * We will map these values to the triggers
+ * because the guitars don't have anything
+ * mapped there.
+ */
+ input_report_abs(sc->input_dev, ABS_Z, rd[44]);
+ input_report_abs(sc->input_dev, ABS_RZ, rd[45]);
+
+ input_sync(sc->input_dev);
+}
+
+static void rb4_ps5_guitar_parse_report(struct sony_sc *sc, u8 *rd, int size)
+{
+ /*
+ * Rock Band 4 PS5 guitars have whammy and
+ * tilt functionality, they're located at
+ * byte 41 and 42 respectively.
+ *
+ * We will map these values to the triggers
+ * because the guitars don't have anything
+ * mapped there.
+ */
+ input_report_abs(sc->input_dev, ABS_Z, rd[41]);
+ input_report_abs(sc->input_dev, ABS_RZ, rd[42]);
+
+ input_sync(sc->input_dev);
+}
+
static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *rd, int size)
{
@@ -950,6 +1041,12 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report,
} else if ((sc->quirks & NSG_MRXU_REMOTE) && rd[0] == 0x02) {
nsg_mrxu_parse_report(sc, rd, size);
return 1;
+ } else if ((sc->quirks & RB4_GUITAR_PS4) && rd[0] == 0x01 && size == 64) {
+ rb4_ps4_guitar_parse_report(sc, rd, size);
+ return 1;
+ } else if ((sc->quirks & RB4_GUITAR_PS5) && rd[0] == 0x01 && size == 64) {
+ rb4_ps5_guitar_parse_report(sc, rd, size);
+ return 1;
}
if (sc->defer_initialization) {
@@ -999,7 +1096,13 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
return sixaxis_mapping(hdev, hi, field, usage, bit, max);
if (sc->quirks & GH_GUITAR_CONTROLLER)
- return guitar_mapping(hdev, hi, field, usage, bit, max);
+ return gh_guitar_mapping(hdev, hi, field, usage, bit, max);
+
+ if (sc->quirks & RB4_GUITAR_PS4)
+ return rb4_guitar_mapping(hdev, hi, field, usage, bit, max);
+
+ if (sc->quirks & RB4_GUITAR_PS5)
+ return rb4_guitar_mapping(hdev, hi, field, usage, bit, max);
/* Let hid-core decide for the others */
return 0;
@@ -2016,6 +2119,8 @@ static int sony_input_configured(struct hid_device *hdev,
} else if (sc->quirks & MOTION_CONTROLLER) {
sony_init_output_report(sc, motion_send_output_report);
+ } else if (sc->quirks & (RB4_GUITAR_PS4 | RB4_GUITAR_PS5)) {
+ sc->input_dev = hidinput->input;
}
if (sc->quirks & SONY_LED_SUPPORT) {
@@ -2271,6 +2376,16 @@ static const struct hid_device_id sony_devices[] = {
/* Guitar Hero Live PS4 guitar dongles */
{ HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE),
.driver_data = GHL_GUITAR_PS4 | GH_GUITAR_CONTROLLER },
+ /* Rock Band 4 PS4 guitars */
+ { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS4_RIFFMASTER),
+ .driver_data = RB4_GUITAR_PS4 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS4_GIBSON_SG),
+ .driver_data = RB4_GUITAR_PS4 },
+ /* Rock Band 4 PS5 guitars */
+ { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS5_RIFFMASTER),
+ .driver_data = RB4_GUITAR_PS5 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS5_GIBSON_SG),
+ .driver_data = RB4_GUITAR_PS5 },
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);
--
2.52.0
^ permalink raw reply related
* Re: [PATCH 2/2] Input: Add support for Wacom W9000-series penabled touchscreens
From: Hendrik Noack @ 2026-01-02 18:28 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-input,
devicetree, linux-kernel
In-Reply-To: <5zfoikfpctpvphtzmthqb3ue5zc43ueriaaesyyqkvjm3b25re@7w2uo4es5har>
Hi Dmitry,
09.12.2025 06:41:44 Dmitry Torokhov <dmitry.torokhov@gmail.com>:
> On Mon, Dec 08, 2025 at 09:35:09PM -0800, Dmitry Torokhov wrote:
>> Hi Hendrik,
>>
>> On Fri, Dec 05, 2025 at 05:49:52PM +0100, Hendrik Noack wrote:
>>> +
>>> + struct gpio_desc *flash_mode_gpio;
>
> Forgot to ask - what does this do? We do not seem to be using it except
> for requesting.
>
> Thanks.
>
> --
> Dmitry
The flash_mode_gpio can be used to start the chip into a flash mode where
new firmware can be flashed. The chip starts in this mode if the pin is high
during the power up. It's in the driver to make sure that this pin is low and the
chip is not accidentally started in flash mode.
Thanks
Hendrik
^ permalink raw reply
* Re: [PATCH 2/2] Input: Add support for Wacom W9000-series penabled touchscreens
From: Hendrik Noack @ 2026-01-02 18:25 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-input,
devicetree, linux-kernel
In-Reply-To: <k5rhkjmttba4aznb3xa44pqaxepsfkbe5ap6g2ln3rcgunvkky@262tpqra76v7>
Hi Dmitry,
09.12.2025 06:35:15 Dmitry Torokhov <dmitry.torokhov@gmail.com>:
> Hi Hendrik,
>
> On Fri, Dec 05, 2025 at 05:49:52PM +0100, Hendrik Noack wrote:
>> Add driver for two Wacom W9007A variants. These are penabled touchscreens
>> supporting passive Wacom Pens and use I2C.
>>
>> Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
>> ---
>> drivers/input/touchscreen/Kconfig | 12 +
>> drivers/input/touchscreen/Makefile | 1 +
>> drivers/input/touchscreen/wacom_w9000.c | 480 ++++++++++++++++++++++++
>> 3 files changed, 493 insertions(+)
>> create mode 100644 drivers/input/touchscreen/wacom_w9000.c
>>
>> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
>> index 7d5b72ee07fa..40f7af0a681a 100644
>> --- a/drivers/input/touchscreen/Kconfig
>> +++ b/drivers/input/touchscreen/Kconfig
>> @@ -610,6 +610,18 @@ config TOUCHSCREEN_WACOM_I2C
>> To compile this driver as a module, choose M here: the module
>> will be called wacom_i2c.
>>
>> +config TOUCHSCREEN_WACOM_W9000
>> + tristate "Wacom W9000-series penabled touchscreen (I2C)"
>> + depends on I2C
>> + help
>> + Say Y here if you have a Wacom W9000-series penabled I2C touchscreen.
>> + This driver supports model W9007A.
>> +
>> + If unsure, say N.
>> +
>> + To compile this driver as a module, choose M here: the module
>> + will be called wacom_w9000.
>> +
>> config TOUCHSCREEN_LPC32XX
>> tristate "LPC32XX touchscreen controller"
>> depends on ARCH_LPC32XX
>> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
>> index ab9abd151078..aa3915df83b2 100644
>> --- a/drivers/input/touchscreen/Makefile
>> +++ b/drivers/input/touchscreen/Makefile
>> @@ -102,6 +102,7 @@ tsc2007-$(CONFIG_TOUCHSCREEN_TSC2007_IIO) += tsc2007_iio.o
>> obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
>> obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
>> obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o
>> +obj-$(CONFIG_TOUCHSCREEN_WACOM_W9000) += wacom_w9000.o
>> obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o
>> obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
>> obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
>> diff --git a/drivers/input/touchscreen/wacom_w9000.c b/drivers/input/touchscreen/wacom_w9000.c
>> new file mode 100644
>> index 000000000000..05c928646bc3
>> --- /dev/null
>> +++ b/drivers/input/touchscreen/wacom_w9000.c
>> @@ -0,0 +1,480 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Wacom W9000-series penabled I2C touchscreen driver
>> + *
>> + * Copyright (c) 2025 Hendrik Noack <hendrik-noack@gmx.de>
>> + *
>> + * Partially based on vendor driver:
>> + * Copyright (C) 2012, Samsung Electronics Co. Ltd.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/i2c.h>
>> +#include <linux/input.h>
>> +#include <linux/input/touchscreen.h>
>> +#include <linux/unaligned.h>
>> +
>> +// Message length
>
> Prefer C-style comments /* */
>
>> +#define COM_COORD_NUM_MAX 12
>> +#define COM_QUERY_NUM_MAX 9
>
> What does "COM" stand for?
It stands for command, but I should use CMD instead.
>> +
>> +// Commands
>> +#define COM_QUERY 0x2a
>> +
>> +struct wacom_w9000_variant {
>> + int com_coord_num;
>
> unsigned?
You're right, would be better.
>
>> + int com_query_num;
>> + char *name;
>
> const?
Makes sense.
>
>> +};
>> +
>> +struct wacom_w9000_data {
>> + struct i2c_client *client;
>> + struct input_dev *input_dev;
>> + const struct wacom_w9000_variant *variant;
>> + unsigned int fw_version;
>> +
>> + struct touchscreen_properties prop;
>> + unsigned int max_pressure;
>> +
>> + struct regulator *regulator;
>> +
>> + struct gpio_desc *flash_mode_gpio;
>> + struct gpio_desc *pen_inserted_gpio;
>> +
>> + unsigned int irq;
>> + unsigned int pen_insert_irq;
>> +
>> + bool pen_inserted;
>> + bool pen_proximity;
>> +};
>> +
>> +static int wacom_w9000_read(struct i2c_client *client, u8 command, int len, char *data)
>> +{
>> + struct i2c_msg xfer[2];
>
> struct i2c_msg xfer[] = {
> {
> .addr = client->addr,
> .buf = &comand,
> .len = sizeof(command),
> },
> {
> ...
> },
> };
Okay, I change it in my next version.
>> + bool retried = false;
>> + int ret;
>> +
>> + /* Write register */
>> + xfer[0].addr = client->addr;
>> + xfer[0].flags = 0;
>> + xfer[0].len = 1;
>> + xfer[0].buf = &command;
>> +
>> + /* Read data */
>> + xfer[1].addr = client->addr;
>> + xfer[1].flags = I2C_M_RD;
>> + xfer[1].len = len;
>> + xfer[1].buf = data;
>> +
>> +retry:
>
> Why do we need a retry? Is it because the controller might be asleep?
> If so can we wake it up explicitly?
Many other devices also have a retry, so I also did it. I thought it makes
sense because it's a connection on a board between a i2c host and
client, that migth have a difficult transmission because of suboptimal
routing.
>
>> + ret = i2c_transfer(client->adapter, xfer, 2);
>> + if (ret == 2) {
>
> ARRAY_SIZE(xfer)
>
You're right.
>> + ret = 0;
>> + } else if (!retried) {
>> + retried = true;
>> + goto retry;
>> + } else {
>> + if (ret >= 0)
>> + ret = -EIO;
>> + dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", __func__, ret);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int wacom_w9000_query(struct wacom_w9000_data *wacom_data)
>> +{
>> + struct i2c_client *client = wacom_data->client;
>> + struct device *dev = &wacom_data->client->dev;
>> + bool retried = false;
>> + int ret;
>> + u8 data[COM_QUERY_NUM_MAX];
>> +
>> +retry:
>> + ret = wacom_w9000_read(client, COM_QUERY, wacom_data->variant->com_query_num, data);
>> + if (ret)
>> + return ret;
>> +
>> + if (data[0] == 0x0f) {
>> + wacom_data->fw_version = get_unaligned_be16(&data[7]);
>> + } else if (!retried) {
>> + retried = true;
>> + goto retry;
>> + } else {
>> + return -EIO;
>> + }
>> +
>> + dev_dbg(dev, "query: %X, %X, %X, %X, %X, %X, %X, %X, %X, %d\n", data[0], data[1], data[2],
>> + data[3], data[4], data[5], data[6], data[7], data[8], retried);
>
> Please print hex data with "%*ph".
Okay
>
>> +
>> + wacom_data->prop.max_x = get_unaligned_be16(&data[1]);
>> + wacom_data->prop.max_y = get_unaligned_be16(&data[3]);
>> + wacom_data->max_pressure = get_unaligned_be16(&data[5]);
>> +
>> + dev_dbg(dev, "max_x:%d, max_y:%d, max_pressure:%d, fw:0x%X", wacom_data->prop.max_x,
>
> fw: %#X
>
>> + wacom_data->prop.max_y, wacom_data->max_pressure,
>> + wacom_data->fw_version);
>> +
>> + return 0;
>> +}
>> +
>> +static void wacom_w9000_coord(struct wacom_w9000_data *wacom_data)
>> +{
>> + struct i2c_client *client = wacom_data->client;
>> + struct device *dev = &wacom_data->client->dev;
>> + int ret;
>> + u8 data[COM_COORD_NUM_MAX];
>> + bool touch, rubber, side_button;
>> + u16 x, y, pressure;
>> + u8 distance;
>> +
>> + ret = i2c_master_recv(client, data, wacom_data->variant->com_coord_num);
>> + if (ret != wacom_data->variant->com_coord_num) {
>> + if (ret >= 0)
>> + ret = -EIO;
>> + dev_err(dev, "%s: i2c receive failed (%d)\n", __func__, ret);
>> + return;
>> + }
>> +
>> + dev_dbg(dev, "data: %X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X", data[0], data[1],
>> + data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10],
>> + data[11]);
>
> "data: %*ph"
>
>> +
>> + if (data[0] & BIT(7)) {
>> + wacom_data->pen_proximity = 1;
>
> = true
>
>> +
>> + touch = !!(data[0] & BIT(4));
>> + side_button = !!(data[0] & BIT(5));
>> + rubber = !!(data[0] & BIT(6));
>> +
>> + x = get_unaligned_be16(&data[1]);
>> + y = get_unaligned_be16(&data[3]);
>> + pressure = get_unaligned_be16(&data[5]);
>> + distance = data[7];
>> +
>> + if (!((x <= wacom_data->prop.max_x) && (y <= wacom_data->prop.max_y))) {
>
> Too many parens. Also maybe
>
> if (x > wacom_data->prop.max_x || y > wacom_data->prop.max_y)
Yeah, I should've just used it from the beginning.
>
>> + dev_warn(dev, "Coordinates out of range x=%d, y=%d", x, y);
>> + return;
>> + }
>> +
>> + touchscreen_report_pos(wacom_data->input_dev, &wacom_data->prop, x, y, false);
>> + input_report_abs(wacom_data->input_dev, ABS_PRESSURE, pressure);
>> + input_report_abs(wacom_data->input_dev, ABS_DISTANCE, distance);
>> + input_report_key(wacom_data->input_dev, BTN_STYLUS, side_button);
>> + input_report_key(wacom_data->input_dev, BTN_TOUCH, touch);
>> + input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, !rubber);
>> + input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, rubber);
>> + input_sync(wacom_data->input_dev);
>> + } else {
>> + if (wacom_data->pen_proximity) {
>
> Can be collapsed "else if"
You're right.
>
>> + input_report_abs(wacom_data->input_dev, ABS_PRESSURE, 0);
>> + input_report_abs(wacom_data->input_dev, ABS_DISTANCE, 0);
>> + input_report_key(wacom_data->input_dev, BTN_STYLUS, 0);
>> + input_report_key(wacom_data->input_dev, BTN_TOUCH, 0);
>> + input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, 0);
>> + input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, 0);
>> + input_sync(wacom_data->input_dev);
>> +
>> + wacom_data->pen_proximity = 0;
>
> = false
>
>> + }
>> + }
>> +}
>> +
>> +static irqreturn_t wacom_w9000_interrupt(int irq, void *dev_id)
>> +{
>> + struct wacom_w9000_data *wacom_data = dev_id;
>> +
>> + wacom_w9000_coord(wacom_data);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static irqreturn_t wacom_w9000_interrupt_pen_insert(int irq, void *dev_id)
>> +{
>> + struct wacom_w9000_data *wacom_data = dev_id;
>> + struct device *dev = &wacom_data->client->dev;
>> + int ret;
>
> int error;
>
>> +
>> + wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
>
> This runs in a thread, use "can sleep" variant.
Okay
>
>> +
>> + input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
>> + input_sync(wacom_data->input_dev);
>> +
>> + if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
>
> What if the regulator is shared with something else? You should not
> operate based on the state, just do what you need (i.e. enable or
> disable).
I'll rework the whole regulator on/off situation.
It's difficult because I also want to take in account if the pen is
currently inserted in the device, then the regulator can stay off until
it's pulled out.
>
>> + ret = regulator_enable(wacom_data->regulator);
>> + if (ret) {
>> + dev_err(dev, "Failed to enable regulators: %d\n", ret);
>> + return IRQ_HANDLED;
>> + }
>> + msleep(200);
>> + enable_irq(wacom_data->irq);
>> + } else if (wacom_data->pen_inserted && regulator_is_enabled(wacom_data->regulator)) {
>> + disable_irq(wacom_data->irq);
>> + regulator_disable(wacom_data->regulator);
>> + }
>> +
>> + dev_dbg(dev, "Pen inserted changed to %d", wacom_data->pen_inserted);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int wacom_w9000_open(struct input_dev *dev)
>> +{
>> + struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
>> + int ret;
>
> int error;
>
>> +
>> + if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
>> + ret = regulator_enable(wacom_data->regulator);
>> + if (ret) {
>> + dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
>> + ret);
>> + return ret;
>> + }
>> + msleep(200);
>> + enable_irq(wacom_data->irq);
>> + }
>> + return 0;
>> +}
>> +
>> +static void wacom_w9000_close(struct input_dev *dev)
>> +{
>> + struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
>> +
>> + if (regulator_is_enabled(wacom_data->regulator)) {
>> + disable_irq(wacom_data->irq);
>> + regulator_disable(wacom_data->regulator);
>> + }
>> +}
>> +
>> +static int wacom_w9000_probe(struct i2c_client *client)
>> +{
>> + struct device *dev = &client->dev;
>> + struct wacom_w9000_data *wacom_data;
>> + struct input_dev *input_dev;
>> + int ret;
>
> int error;
>
>> + u32 val;
>> +
>> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
>> + dev_err(dev, "i2c_check_functionality error\n");
>> + return -EIO;
>> + }
>> +
>> + wacom_data = devm_kzalloc(dev, sizeof(*wacom_data), GFP_KERNEL);
>> + if (!wacom_data)
>> + return -ENOMEM;
>> +
>> + wacom_data->variant = i2c_get_match_data(client);
>> +
>> + wacom_data->client = client;
>> +
>> + input_dev = devm_input_allocate_device(dev);
>> + if (!input_dev)
>> + return -ENOMEM;
>> + wacom_data->input_dev = input_dev;
>> +
>> + wacom_data->irq = client->irq;
>> + i2c_set_clientdata(client, wacom_data);
>> +
>> + wacom_data->regulator = devm_regulator_get(dev, "vdd");
>> + if (IS_ERR(wacom_data->regulator))
>> + return dev_err_probe(dev, PTR_ERR(wacom_data->regulator),
>> + "Failed to get regulators\n");
>> +
>> + wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
>> + if (IS_ERR(wacom_data->flash_mode_gpio))
>> + return dev_err_probe(dev, PTR_ERR(wacom_data->flash_mode_gpio),
>> + "Failed to get flash-mode gpio\n");
>> +
>> + wacom_data->pen_inserted_gpio = devm_gpiod_get_optional(dev, "pen-inserted", GPIOD_IN);
>> + if (IS_ERR(wacom_data->pen_inserted_gpio))
>> + return dev_err_probe(dev, PTR_ERR(wacom_data->pen_inserted_gpio),
>> + "Failed to get pen-insert gpio\n");
>> +
>> + ret = regulator_enable(wacom_data->regulator);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "Failed to enable regulators\n");
>> +
>> + msleep(200);
>> +
>> + ret = wacom_w9000_query(wacom_data);
>> + if (ret)
>> + goto err_disable_regulators;
>
> I do not think you need power past this point until you open the device.
> Maybe turn it off right here?
Correct, this will simplify some things.
>
>> +
>> + input_dev->name = wacom_data->variant->name;
>> + input_dev->id.bustype = BUS_I2C;
>> + input_dev->dev.parent = dev;
>> + input_dev->id.vendor = 0x56a;
>> + input_dev->id.version = wacom_data->fw_version;
>> + input_dev->open = wacom_w9000_open;
>> + input_dev->close = wacom_w9000_close;
>> +
>> + input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
>> + input_set_capability(input_dev, EV_KEY, BTN_TOOL_PEN);
>> + input_set_capability(input_dev, EV_KEY, BTN_TOOL_RUBBER);
>> + input_set_capability(input_dev, EV_KEY, BTN_STYLUS);
>> +
>> + // Calculate x and y resolution from size in devicetree
>> + ret = device_property_read_u32(dev, "touchscreen-x-mm", &val);
>> + if (ret)
>> + input_abs_set_res(input_dev, ABS_X, 100);
>
> If you do not have resolution data simply do not set it.
Okay.
>
>> + else
>> + input_abs_set_res(input_dev, ABS_X, wacom_data->prop.max_x / val);
>
> Don't you parse prop below so here max_x and max_y are both 0?
They're parsed in the wacom_w9000_query. I should still move them
below the touchscreen_parse_properties, just in case they're changed
in there.
>
>> + ret = device_property_read_u32(dev, "touchscreen-y-mm", &val);
>> + if (ret)
>> + input_abs_set_res(input_dev, ABS_Y, 100);
>> + else
>> + input_abs_set_res(input_dev, ABS_Y, wacom_data->prop.max_y / val);
>> +
>> + input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
>> + input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
>> + input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
>> + input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
>> +
>> + touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
>> +
>> + ret = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
>> + IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
>> + if (ret) {
>> + dev_err(dev, "Failed to register interrupt\n");
>> + goto err_disable_regulators;
>> + }
>> +
>> + if (wacom_data->pen_inserted_gpio) {
>> + input_set_capability(input_dev, EV_SW, SW_PEN_INSERTED);
>> + wacom_data->pen_insert_irq = gpiod_to_irq(wacom_data->pen_inserted_gpio);
>> + ret = devm_request_threaded_irq(dev, wacom_data->pen_insert_irq, NULL,
>> + wacom_w9000_interrupt_pen_insert, IRQF_ONESHOT |
>> + IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
>> + IRQF_TRIGGER_FALLING, "wacom_pen_insert",
>
> Rely on DT to define triggers. Use IRQF_ONESHOT only.
For this I would also need to specify this interrupt in the DT. This
interrupt would then need to have the same pin as specified for
pen_inserted_gpio and I can't only have the interrupt for it in the DT,
because I need pen_inserted_gpio to find out if the pen is inserted or not,
so that I can set power accordingly.
>
>> + wacom_data);
>> + if (ret) {
>> + dev_err(dev, "Failed to register pen-insert interrupt\n");
>> + goto err_disable_regulators;
>> + }
>> +
>> + wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
>> + if (wacom_data->pen_inserted)
>> + regulator_disable(wacom_data->regulator);
>> + else
>> + enable_irq(wacom_data->irq);
>> + } else {
>> + enable_irq(wacom_data->irq);
>
> Can this be moved into "open"?
Makes sense
>
>> + }
>> +
>> + input_set_drvdata(input_dev, wacom_data);
>> +
>> + input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
>> + input_sync(wacom_data->input_dev);
>> +
>> + if (wacom_data->pen_inserted_gpio)
>> + enable_irq(wacom_data->pen_insert_irq);
>> +
>> + ret = input_register_device(wacom_data->input_dev);
>> + if (ret) {
>> + dev_err(dev, "Failed to register input device: %d\n", ret);
>> + goto err_disable_regulators;
>> + }
>> +
>> + return 0;
>> +
>> +err_disable_regulators:
>> + regulator_disable(wacom_data->regulator);
>> + return ret;
>> +}
>> +
>> +static void wacom_w9000_remove(struct i2c_client *client)
>> +{
>> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
>> +
>> + if (regulator_is_enabled(wacom_data->regulator))
>> + regulator_disable(wacom_data->regulator);
>
> Please move this to "close" and drop wacom_w9000_remove() altogether.
Alright, this makes things easier.
>
>> +}
>> +
>> +static int wacom_w9000_suspend(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
>> + struct input_dev *input_dev = wacom_data->input_dev;
>> +
>> + mutex_lock(&input_dev->mutex);
>
> guard(mutex)(&input_dev->mutex);
Okay
>
>> +
>> + if (regulator_is_enabled(wacom_data->regulator)) {
>> + disable_irq(wacom_data->irq);
>> + regulator_disable(wacom_data->regulator);
>> + }
>> +
>> + mutex_unlock(&input_dev->mutex);
>> +
>> + return 0;
>> +}
>> +
>> +static int wacom_w9000_resume(struct device *dev)
>> +{
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
>> + struct input_dev *input_dev = wacom_data->input_dev;
>> + int ret = 0;
>> +
>> + mutex_lock(&input_dev->mutex);
>
> guard(mutex)(&input_dev->mutex);
>> +
>> + if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
>> + ret = regulator_enable(wacom_data->regulator);
>> + if (ret) {
>> + dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
>> + ret);
>> + } else {
>> + msleep(200);
>> + enable_irq(wacom_data->irq);
>> + }
>> + }
>> +
>> + mutex_unlock(&input_dev->mutex);
>> +
>> + return ret;
>> +}
>> +
>> +static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
>> +
>> +static const struct wacom_w9000_variant w9007a_lt03 = {
>> + .com_coord_num = 8,
>> + .com_query_num = 9,
>> + .name = "Wacom W9007 LT03 Digitizer",
>> +};
>> +
>> +static const struct wacom_w9000_variant w9007a_v1 = {
>> + .com_coord_num = 12,
>> + .com_query_num = 9,
>> + .name = "Wacom W9007 V1 Digitizer",
>> +};
>> +
>> +static const struct of_device_id wacom_w9000_of_match[] = {
>> + { .compatible = "wacom,w9007a-lt03", .data = &w9007a_lt03, },
>> + { .compatible = "wacom,w9007a-v1", .data = &w9007a_v1, },
>> + {},
>
> { }
>
> No need for trailing comma on a sentinel entry.
Okay
>
>> +};
>> +MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
>> +
>> +static const struct i2c_device_id wacom_w9000_id[] = {
>> + { .name = "w9007a-lt03", .driver_data = (kernel_ulong_t)&w9007a_lt03 },
>> + { .name = "w9007a-v1", .driver_data = (kernel_ulong_t)&w9007a_v1 },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
>> +
>> +static struct i2c_driver wacom_w9000_driver = {
>> + .driver = {
>> + .name = "wacom_w9000",
>> + .of_match_table = wacom_w9000_of_match,
>> + .pm = pm_sleep_ptr(&wacom_w9000_pm),
>> + },
>> + .probe = wacom_w9000_probe,
>> + .remove = wacom_w9000_remove,
>> + .id_table = wacom_w9000_id,
>> +};
>> +module_i2c_driver(wacom_w9000_driver);
>> +
>> +/* Module information */
>> +MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
>> +MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
>> +MODULE_LICENSE("GPL");
>
> Thanks.
>
> --
> Dmitry
Thanks for your feedback. I'm going to incorporate it in my next version.
Hendrik
^ permalink raw reply
* Re: [PATCH 5/5] selftests/bpf: make cfi_stubs globals const
From: Caleb Sander Mateos @ 2026-01-02 16:19 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: bot+bpf-ci, Jiri Kosina, Benjamin Tissoires, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Martin KaFai Lau, Eduard, Song Liu, Yonghong Song, KP Singh,
Stanislav Fomichev, Hao Luo, Jiri Olsa, Tejun Heo, David Vernet,
Andrea Righi, Changwoo Min, Ingo Molnar, Peter Zijlstra,
Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Benjamin Segall, Mel Gorman, Valentin Schneider, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Jamal Hadi Salim, Cong Wang, Jiri Pirko, D. Wythe,
Dust Li, sidraya, wenjia, mjambigi, Tony Lu, guwen, Shuah Khan,
Maxime Coquelin, Alexandre Torgue, open list:HID CORE LAYER, LKML,
bpf, Network Development, sched-ext, linux-rdma, linux-s390,
open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
linux-arm-kernel, Martin KaFai Lau, Chris Mason, Ihor Solodrai
In-Reply-To: <CAADnVQJ0Xhmx0ZyTKbWqaiiX7QwghMznzjDL1CNmraXM4d+T7A@mail.gmail.com>
On Wed, Dec 31, 2025 at 6:10 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Wed, Dec 31, 2025 at 4:28 PM Caleb Sander Mateos
> <csander@purestorage.com> wrote:
> >
> > On Wed, Dec 31, 2025 at 10:13 AM Alexei Starovoitov
> > <alexei.starovoitov@gmail.com> wrote:
> > >
> > > On Wed, Dec 31, 2025 at 10:09 AM Caleb Sander Mateos
> > > <csander@purestorage.com> wrote:
> > > >
> > > > On Wed, Dec 31, 2025 at 10:04 AM <bot+bpf-ci@kernel.org> wrote:
> > > > >
> > > > > > diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > > > index 90c4b1a51de6..5e460b1dbdb6 100644
> > > > > > --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > > > +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > >
> > > > > [ ... ]
> > > > >
> > > > > > @@ -1275,7 +1275,7 @@ bpf_testmod_ops__test_return_ref_kptr(int dummy, struct task_struct *task__ref,
> > > > > > return NULL;
> > > > > > }
> > > > > >
> > > > > > -static struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > > > +static const struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > > > .test_1 = bpf_testmod_test_1,
> > > > > > .test_2 = bpf_testmod_test_2,
> > > > >
> > > > > Is it safe to make __bpf_testmod_ops const here? In bpf_testmod_init(),
> > > > > this struct is modified at runtime:
> > > > >
> > > > > tramp = (void **)&__bpf_testmod_ops.tramp_1;
> > > > > while (tramp <= (void **)&__bpf_testmod_ops.tramp_40)
> > > > > *tramp++ = bpf_testmod_tramp;
> > > > >
> > > > > Writing to a const-qualified object is undefined behavior and may cause a
> > > > > protection fault when the compiler places this in read-only memory. Would
> > > > > the module fail to load on systems where .rodata is actually read-only?
> > > >
> > > > Yup, that's indeed the bug caught by KASAN. Missed this mutation at
> > > > init time, I'll leave __bpf_testmod_ops as mutable.
> > >
> > > No. You're missing the point. The whole patch set is no go.
> > > The pointer to cfi stub can be updated just as well.
> >
> > Do you mean the BPF core code would modify the struct pointed to by
> > cfi_stubs? Or some BPF struct_ops implementation (like this one in
> > bpf_testmod.c) would modify it? If you're talking about the BPF core
> > code, could you point out where this happens? I couldn't find it when
> > looking through the handful of uses of cfi_stubs (see patch 1/5). Or
> > are you talking about some hypothetical future code that would write
> > through the cfi_stubs pointer? If you're talking about a struct_ops
> > implementation, I certainly agree it could modify the struct pointed
> > to by cfi_stubs (before calling register_bpf_struct_ops()). But then
> > the struct_ops implementation doesn't have to declare the global
> > variable as const. A non-const pointer is allowed anywhere a const
> > pointer is expected.
>
> You're saying that void const * cfi_stubs; pointing to non-const
> __bpf_testmod_ops is somehow ok? No. This right into undefined behavior.
> Not going to allow that.
How is that undefined behavior? Wouldn't the following be UB by the
same reasoning?
void takes_const(const int *x);
void f(void)
{
int not_const = 123;
takes_const(¬_const);
}
A const-qualified pointer type just prevents that pointer from being
used to mutate the memory it points to. It doesn't guarantee that the
memory it points to is marked readonly.
^ permalink raw reply
* Re: [PATCH 4/6] dt-bindings: power: supply: google,goldfish-battery: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-01-02 12:21 UTC (permalink / raw)
To: Kuan-Wei Chiu
Cc: airlied, simona, maarten.lankhorst, mripard, tzimmermann, robh,
krzk+dt, conor+dt, dmitry.torokhov, sre, gregkh, jirislaby,
lgirdwood, broonie, jserv, eleanor15x, dri-devel, devicetree,
linux-kernel, linux-input, linux-pm, linux-serial, linux-sound
In-Reply-To: <20251230181031.3191565-5-visitorckw@gmail.com>
On Tue, Dec 30, 2025 at 06:10:29PM +0000, Kuan-Wei Chiu wrote:
> +---
> +$id: http://devicetree.org/schemas/power/supply/google,goldfish-battery.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Android Goldfish Battery
> +
> +maintainers:
> + - Kuan-Wei Chiu <visitorckw@gmail.com>
> +
Same comments.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 3/6] dt-bindings: input: google,goldfish-events-keypad: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-01-02 12:20 UTC (permalink / raw)
To: Kuan-Wei Chiu
Cc: airlied, simona, maarten.lankhorst, mripard, tzimmermann, robh,
krzk+dt, conor+dt, dmitry.torokhov, sre, gregkh, jirislaby,
lgirdwood, broonie, jserv, eleanor15x, dri-devel, devicetree,
linux-kernel, linux-input, linux-pm, linux-serial, linux-sound
In-Reply-To: <20251230181031.3191565-4-visitorckw@gmail.com>
On Tue, Dec 30, 2025 at 06:10:28PM +0000, Kuan-Wei Chiu wrote:
> +title: Android Goldfish Events Keypad
> +
> +maintainers:
> + - Kuan-Wei Chiu <visitorckw@gmail.com>
> +
> +description:
> + Android goldfish events keypad device generated by android emulator.
> +
Not an input device? No input.yaml reference?
> +properties:
> + compatible:
> + const: google,goldfish-events-keypad
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + keypad@9040000 {
> + compatible = "google,goldfish-events-keypad";
> + reg = <0x9040000 0x1000>;
> + interrupts = <0x5>;
This should be decimal, not hex.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/6] dt-bindings: misc: google,android-pipe: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-01-02 12:19 UTC (permalink / raw)
To: Kuan-Wei Chiu
Cc: airlied, simona, maarten.lankhorst, mripard, tzimmermann, robh,
krzk+dt, conor+dt, dmitry.torokhov, sre, gregkh, jirislaby,
lgirdwood, broonie, jserv, eleanor15x, dri-devel, devicetree,
linux-kernel, linux-input, linux-pm, linux-serial, linux-sound
In-Reply-To: <20251230181031.3191565-3-visitorckw@gmail.com>
On Tue, Dec 30, 2025 at 06:10:27PM +0000, Kuan-Wei Chiu wrote:
> Convert the Android Goldfish QEMU Pipe binding to DT schema format.
> Move the file to the misc directory as it represents a miscellaneous
> communication device.
> Update the example node name to 'pipe' to comply with generic node
> naming standards and fix the mismatch between unit address and reg
> property in the original example.
>
> Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
> ---
> .../devicetree/bindings/goldfish/pipe.txt | 17 ---------
> .../bindings/misc/google,android-pipe.yaml | 38 +++++++++++++++++++
> 2 files changed, 38 insertions(+), 17 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/goldfish/pipe.txt
> create mode 100644 Documentation/devicetree/bindings/misc/google,android-pipe.yaml
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/6] dt-bindings: serial: google,goldfish-tty: Convert to DT schema
From: Krzysztof Kozlowski @ 2026-01-02 12:18 UTC (permalink / raw)
To: Kuan-Wei Chiu
Cc: airlied, simona, maarten.lankhorst, mripard, tzimmermann, robh,
krzk+dt, conor+dt, dmitry.torokhov, sre, gregkh, jirislaby,
lgirdwood, broonie, jserv, eleanor15x, dri-devel, devicetree,
linux-kernel, linux-input, linux-pm, linux-serial, linux-sound
In-Reply-To: <20251230181031.3191565-2-visitorckw@gmail.com>
On Tue, Dec 30, 2025 at 06:10:26PM +0000, Kuan-Wei Chiu wrote:
> Convert the Google Goldfish TTY binding to DT schema format.
> Move the file to the serial directory to match the subsystem.
> Update the example node name to 'serial' to comply with generic node
> naming standards.
>
> Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
> ---
> .../devicetree/bindings/goldfish/tty.txt | 17 ---------
> .../bindings/serial/google,goldfish-tty.yaml | 38 +++++++++++++++++++
> 2 files changed, 38 insertions(+), 17 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/goldfish/tty.txt
> create mode 100644 Documentation/devicetree/bindings/serial/google,goldfish-tty.yaml
>
> diff --git a/Documentation/devicetree/bindings/goldfish/tty.txt b/Documentation/devicetree/bindings/goldfish/tty.txt
> deleted file mode 100644
> index 82648278da77..000000000000
> --- a/Documentation/devicetree/bindings/goldfish/tty.txt
> +++ /dev/null
> @@ -1,17 +0,0 @@
> -Android Goldfish TTY
> -
> -Android goldfish tty device generated by android emulator.
> -
> -Required properties:
> -
> -- compatible : should contain "google,goldfish-tty" to match emulator
> -- reg : <registers mapping>
> -- interrupts : <interrupt mapping>
> -
> -Example:
> -
> - goldfish_tty@1f004000 {
> - compatible = "google,goldfish-tty";
> - reg = <0x1f004000 0x1000>;
> - interrupts = <0xc>;
> - };
> diff --git a/Documentation/devicetree/bindings/serial/google,goldfish-tty.yaml b/Documentation/devicetree/bindings/serial/google,goldfish-tty.yaml
> new file mode 100644
> index 000000000000..08fa12449a01
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/google,goldfish-tty.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/serial/google,goldfish-tty.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Google Goldfish TTY
> +
> +maintainers:
> + - Kuan-Wei Chiu <visitorckw@gmail.com>
> +
Missing allOf to /schemas/serial/serial, unless this is not a serial, but then your
commit msg should explain that.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] HID: quirks: Add another Chicony HP 5MP Cameras to hid_ignore_list
From: Chris Chiu @ 2026-01-02 6:56 UTC (permalink / raw)
To: jikos, bentiss; +Cc: linux-input, Chris Chiu
Another Chicony Electronics HP 5MP Camera with USB ID 04F2:B882
reports a HID sensor interface that is not actually implemented.
Add the device to the HID ignore list so the bogus sensor is never
exposed to userspace. Then the system won't hang when runtime PM
tries to wake the unresponsive device.
Signed-off-by: Chris Chiu <chris.chiu@canonical.com>
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-quirks.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d31711f1aaec..e8a1a86313b7 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -317,6 +317,7 @@
#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA 0xb824
#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2 0xb82c
+#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA3 0xb882
#define USB_VENDOR_ID_CHUNGHWAT 0x2247
#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index c89a015686c0..3cf7971d4974 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -769,6 +769,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI4713) },
--
2.43.0
^ permalink raw reply related
* [PATCH 1/1] Input: xpad - add support for Beitong KP-series controllers
From: Zixing Liu @ 2026-01-02 3:01 UTC (permalink / raw)
To: linux-input, linux-kernel; +Cc: Dmitry Torokhov, Zixing Liu
In-Reply-To: <20260102030154.197749-2-liushuyu@aosc.io>
This commit also adds a field to usb_xpad and changed
how xpad_prepare_next_init_packet determines whether init packets need
to be send in order to handle special quirks needed for supporting
Beitong KP-series controllers.
Signed-off-by: Zixing Liu <liushuyu@aosc.io>
---
drivers/input/joystick/xpad.c | 57 ++++++++++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 363d50949386..fa874e4cb586 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -106,6 +106,7 @@
#define PKT_XBE2_FW_5_11 4
#define FLAG_DELAY_INIT BIT(0)
+#define FLAG_FORCE_INIT BIT(1)
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
@@ -360,6 +361,34 @@ static const struct xpad_device {
{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
{ 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 },
+ { 0x20bc, 0x5125, "Beitong KP20A/KP40A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5126, "Beitong KP20A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5127, "Beitong KP20A/KP40A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5128, "Beitong KP20A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x512f, "Beitong KP70A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5130, "Beitong KP70A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5133, "Beitong KP50B Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5134, "Beitong KP50B Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5145, "Beitong KP40A/KP40B Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5146, "Beitong KP40A/KP40B Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5149, "Beitong KP50C Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x514a, "Beitong KP50C Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5150, "Beitong KP50D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5151, "Beitong KP50D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5152, "Beitong KP50E Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5153, "Beitong KP50E Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5154, "Beitong KP40D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5155, "Beitong KP40D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5158, "Beitong KP20D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5159, "Beitong KP20D Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x515b, "Beitong KP40D Controller (White)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x515c, "Beitong KP40D Controller (White)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x515d, "Beitong KP40F Controller (White)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x515e, "Beitong KP40F Controller (White)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x515f, "Beitong KP70A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5160, "Beitong KP70A Controller", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x5169, "Beitong KP40F Controller (Black)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
+ { 0x20bc, 0x516a, "Beitong KP40F Controller (Black)", 0, XTYPE_XBOX360, FLAG_FORCE_INIT },
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x2064, "PowerA Wired Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE },
@@ -562,6 +591,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x1a86), /* Nanjing Qinheng Microelectronics (WCH) */
XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */
XPAD_XBOX360_VENDOR(0x1ee9), /* ZOTAC Technology Limited */
+ XPAD_XBOX360_VENDOR(0x20bc), /* ShanWan or Beitong controllers */
XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */
XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */
XPAD_XBOX360_VENDOR(0x2345), /* Machenike Controllers */
@@ -724,6 +754,15 @@ static const u8 xboxone_rumbleend_init[] = {
0x00, GIP_MOTOR_ALL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+/*
+ * Beitong controllers require a specific sequence of
+ * acknowledge and probe packets during initialization to
+ * enter the XINPUT mode correctly.
+ */
+static const u8 btp_ack_probe_packet[] = { GIP_CMD_ACK, 0x3, GIP_SEQ0 };
+static const u8 btp_probe_response_packet[] = { GIP_CMD_ANNOUNCE, 0x8,
+ GIP_SEQ0 };
+
/*
* This specifies the selection of init packets that a gamepad
* will be sent on init *and* the order in which they will be
@@ -739,6 +778,10 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
XBOXONE_INIT_PKT(0x045e, 0x0b00, extra_input_packet_init),
XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_led_on),
XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_auth_done),
+ XBOXONE_INIT_PKT(0x20bc, 0x0000, btp_ack_probe_packet),
+ XBOXONE_INIT_PKT(0x20bc, 0x0000, btp_probe_response_packet),
+ XBOXONE_INIT_PKT(0x20bc, 0x0000, btp_ack_probe_packet),
+ XBOXONE_INIT_PKT(0x20bc, 0x0000, btp_ack_probe_packet),
XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
@@ -800,6 +843,7 @@ struct usb_xpad {
time64_t mode_btn_down_ts;
bool delay_init; /* init packets should be delayed */
bool delayed_init_done;
+ bool force_init; /* send init packets even if it is not a xbox one device */
};
static int xpad_init_input(struct usb_xpad *xpad);
@@ -1275,7 +1319,7 @@ static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad)
{
const struct xboxone_init_packet *init_packet;
- if (xpad->xtype != XTYPE_XBOXONE)
+ if (xpad->xtype != XTYPE_XBOXONE && !xpad->force_init)
return false;
/*
@@ -1814,6 +1858,15 @@ static int xpad_start_input(struct usb_xpad *xpad)
*/
u8 dummy[20];
+ /*
+ * Some third-party Xbox 360-style controllers
+ * require sending Xbox One messages to finish initialization.
+ */
+ {
+ guard(spinlock_irqsave)(&xpad->odata_lock);
+ xpad_prepare_next_init_packet(xpad);
+ }
+
error = usb_control_msg_recv(xpad->udev, 0,
/* bRequest */ 0x01,
/* bmRequestType */
@@ -2104,6 +2157,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->name = xpad_device[i].name;
if (xpad_device[i].flags & FLAG_DELAY_INIT)
xpad->delay_init = true;
+ if (xpad_device[i].flags & FLAG_FORCE_INIT)
+ xpad->force_init = true;
xpad->packet_type = PKT_XB;
INIT_WORK(&xpad->work, xpad_presence_work);
--
2.52.0
^ permalink raw reply related
* [PATCH 0/1] xpad - add support for Beitong KP-series controllers
From: Zixing Liu @ 2026-01-02 3:01 UTC (permalink / raw)
To: linux-input, linux-kernel; +Cc: Dmitry Torokhov, Zixing Liu
This particular series has several input modes that the controller will
try to select when the controller is powered on (either connected via
wired USB connection or using the dongle provided in the box).
This series of controllers will try to see if specific Xbox One packets were
sent during the probing phase and will power-cycle themselves when they fail to
see these packets. If the controller power-cycles more than three times,
it will change to the next input mode it supports (e.g. Nintendo Switch
mode).
After the Xbox One packets were observed, they will use Xbox 360
protocol to report the input events.
Tested on a Beitong KP-20A controller via USB connection, Bluetooth connection
and via stock wireless dongle.
Zixing Liu (1):
Input: xpad - add support for Beitong KP-series controllers
drivers/input/joystick/xpad.c | 55 ++++++++++++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
--
2.52.0
^ permalink raw reply
* Re: [PATCH 5/5] selftests/bpf: make cfi_stubs globals const
From: Alexei Starovoitov @ 2026-01-01 2:10 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: bot+bpf-ci, Jiri Kosina, Benjamin Tissoires, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Martin KaFai Lau, Eduard, Song Liu, Yonghong Song, KP Singh,
Stanislav Fomichev, Hao Luo, Jiri Olsa, Tejun Heo, David Vernet,
Andrea Righi, Changwoo Min, Ingo Molnar, Peter Zijlstra,
Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Benjamin Segall, Mel Gorman, Valentin Schneider, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Jamal Hadi Salim, Cong Wang, Jiri Pirko, D. Wythe,
Dust Li, sidraya, wenjia, mjambigi, Tony Lu, guwen, Shuah Khan,
Maxime Coquelin, Alexandre Torgue, open list:HID CORE LAYER, LKML,
bpf, Network Development, sched-ext, linux-rdma, linux-s390,
open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
linux-arm-kernel, Martin KaFai Lau, Chris Mason, Ihor Solodrai
In-Reply-To: <CADUfDZq5Bf8mVD9o=VHsUqYgqyMJx82_fhy73ZzkvawQi2Ko2g@mail.gmail.com>
On Wed, Dec 31, 2025 at 4:28 PM Caleb Sander Mateos
<csander@purestorage.com> wrote:
>
> On Wed, Dec 31, 2025 at 10:13 AM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Wed, Dec 31, 2025 at 10:09 AM Caleb Sander Mateos
> > <csander@purestorage.com> wrote:
> > >
> > > On Wed, Dec 31, 2025 at 10:04 AM <bot+bpf-ci@kernel.org> wrote:
> > > >
> > > > > diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > > index 90c4b1a51de6..5e460b1dbdb6 100644
> > > > > --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > > +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > >
> > > > [ ... ]
> > > >
> > > > > @@ -1275,7 +1275,7 @@ bpf_testmod_ops__test_return_ref_kptr(int dummy, struct task_struct *task__ref,
> > > > > return NULL;
> > > > > }
> > > > >
> > > > > -static struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > > +static const struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > > .test_1 = bpf_testmod_test_1,
> > > > > .test_2 = bpf_testmod_test_2,
> > > >
> > > > Is it safe to make __bpf_testmod_ops const here? In bpf_testmod_init(),
> > > > this struct is modified at runtime:
> > > >
> > > > tramp = (void **)&__bpf_testmod_ops.tramp_1;
> > > > while (tramp <= (void **)&__bpf_testmod_ops.tramp_40)
> > > > *tramp++ = bpf_testmod_tramp;
> > > >
> > > > Writing to a const-qualified object is undefined behavior and may cause a
> > > > protection fault when the compiler places this in read-only memory. Would
> > > > the module fail to load on systems where .rodata is actually read-only?
> > >
> > > Yup, that's indeed the bug caught by KASAN. Missed this mutation at
> > > init time, I'll leave __bpf_testmod_ops as mutable.
> >
> > No. You're missing the point. The whole patch set is no go.
> > The pointer to cfi stub can be updated just as well.
>
> Do you mean the BPF core code would modify the struct pointed to by
> cfi_stubs? Or some BPF struct_ops implementation (like this one in
> bpf_testmod.c) would modify it? If you're talking about the BPF core
> code, could you point out where this happens? I couldn't find it when
> looking through the handful of uses of cfi_stubs (see patch 1/5). Or
> are you talking about some hypothetical future code that would write
> through the cfi_stubs pointer? If you're talking about a struct_ops
> implementation, I certainly agree it could modify the struct pointed
> to by cfi_stubs (before calling register_bpf_struct_ops()). But then
> the struct_ops implementation doesn't have to declare the global
> variable as const. A non-const pointer is allowed anywhere a const
> pointer is expected.
You're saying that void const * cfi_stubs; pointing to non-const
__bpf_testmod_ops is somehow ok? No. This right into undefined behavior.
Not going to allow that.
^ permalink raw reply
* Re: [PATCH 5/5] selftests/bpf: make cfi_stubs globals const
From: Caleb Sander Mateos @ 2026-01-01 0:28 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: bot+bpf-ci, Jiri Kosina, Benjamin Tissoires, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Martin KaFai Lau, Eduard, Song Liu, Yonghong Song, KP Singh,
Stanislav Fomichev, Hao Luo, Jiri Olsa, Tejun Heo, David Vernet,
Andrea Righi, Changwoo Min, Ingo Molnar, Peter Zijlstra,
Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Benjamin Segall, Mel Gorman, Valentin Schneider, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Jamal Hadi Salim, Cong Wang, Jiri Pirko, D. Wythe,
Dust Li, sidraya, wenjia, mjambigi, Tony Lu, guwen, Shuah Khan,
Maxime Coquelin, Alexandre Torgue, open list:HID CORE LAYER, LKML,
bpf, Network Development, sched-ext, linux-rdma, linux-s390,
open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
linux-arm-kernel, Martin KaFai Lau, Chris Mason, Ihor Solodrai
In-Reply-To: <CAADnVQKXUUNn=P=2-UECF1X7SR+oqm4xsr-2trpgTy1q+0c5FQ@mail.gmail.com>
On Wed, Dec 31, 2025 at 10:13 AM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Wed, Dec 31, 2025 at 10:09 AM Caleb Sander Mateos
> <csander@purestorage.com> wrote:
> >
> > On Wed, Dec 31, 2025 at 10:04 AM <bot+bpf-ci@kernel.org> wrote:
> > >
> > > > diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > index 90c4b1a51de6..5e460b1dbdb6 100644
> > > > --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > > +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > >
> > > [ ... ]
> > >
> > > > @@ -1275,7 +1275,7 @@ bpf_testmod_ops__test_return_ref_kptr(int dummy, struct task_struct *task__ref,
> > > > return NULL;
> > > > }
> > > >
> > > > -static struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > +static const struct bpf_testmod_ops __bpf_testmod_ops = {
> > > > .test_1 = bpf_testmod_test_1,
> > > > .test_2 = bpf_testmod_test_2,
> > >
> > > Is it safe to make __bpf_testmod_ops const here? In bpf_testmod_init(),
> > > this struct is modified at runtime:
> > >
> > > tramp = (void **)&__bpf_testmod_ops.tramp_1;
> > > while (tramp <= (void **)&__bpf_testmod_ops.tramp_40)
> > > *tramp++ = bpf_testmod_tramp;
> > >
> > > Writing to a const-qualified object is undefined behavior and may cause a
> > > protection fault when the compiler places this in read-only memory. Would
> > > the module fail to load on systems where .rodata is actually read-only?
> >
> > Yup, that's indeed the bug caught by KASAN. Missed this mutation at
> > init time, I'll leave __bpf_testmod_ops as mutable.
>
> No. You're missing the point. The whole patch set is no go.
> The pointer to cfi stub can be updated just as well.
Do you mean the BPF core code would modify the struct pointed to by
cfi_stubs? Or some BPF struct_ops implementation (like this one in
bpf_testmod.c) would modify it? If you're talking about the BPF core
code, could you point out where this happens? I couldn't find it when
looking through the handful of uses of cfi_stubs (see patch 1/5). Or
are you talking about some hypothetical future code that would write
through the cfi_stubs pointer? If you're talking about a struct_ops
implementation, I certainly agree it could modify the struct pointed
to by cfi_stubs (before calling register_bpf_struct_ops()). But then
the struct_ops implementation doesn't have to declare the global
variable as const. A non-const pointer is allowed anywhere a const
pointer is expected.
Thanks,
Caleb
^ permalink raw reply
* [PATCH] HID: i2c-hid: fix potential buffer overflow in i2c_hid_get_report()
From: Kwok Kin Ming @ 2025-12-31 18:18 UTC (permalink / raw)
To: jikos, bentiss; +Cc: Kwok Kin Ming, linux-input, linux-kernel
`i2c_hid_xfer` is used to read `recv_len + sizeof(__le16)` bytes of data
into `ihid->rawbuf`.
The former can come from the userspace in the hidraw driver and is only
bounded by HID_MAX_BUFFER_SIZE(16384) by default (unless we also set
`max_buffer_size` field of `struct hid_ll_driver` which we do not).
The latter has size determined at runtime by the maximum size of
different report types you could receive on any particular device and
can be a much smaller value.
Fix this by truncating `recv_len` to `ihid->bufsize - sizeof(__le16)`.
The impact is low since access to hidraw devices requires root.
Signed-off-by: Kwok Kin Ming <kenkinming2002@gmail.com>
---
drivers/hid/i2c-hid/i2c-hid-core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 63f46a2e5..5a183af3d 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -286,6 +286,7 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,
* In addition to report data device will supply data length
* in the first 2 bytes of the response, so adjust .
*/
+ recv_len = min(recv_len, ihid->bufsize - sizeof(__le16));
error = i2c_hid_xfer(ihid, ihid->cmdbuf, length,
ihid->rawbuf, recv_len + sizeof(__le16));
if (error) {
--
2.52.0
^ permalink raw reply related
* Re: [PATCH 5/5] selftests/bpf: make cfi_stubs globals const
From: Alexei Starovoitov @ 2025-12-31 18:13 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: bot+bpf-ci, Jiri Kosina, Benjamin Tissoires, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Martin KaFai Lau, Eduard, Song Liu, Yonghong Song, KP Singh,
Stanislav Fomichev, Hao Luo, Jiri Olsa, Tejun Heo, David Vernet,
Andrea Righi, Changwoo Min, Ingo Molnar, Peter Zijlstra,
Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
Benjamin Segall, Mel Gorman, Valentin Schneider, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Jamal Hadi Salim, Cong Wang, Jiri Pirko, D. Wythe,
Dust Li, sidraya, wenjia, mjambigi, Tony Lu, guwen, Shuah Khan,
Maxime Coquelin, Alexandre Torgue, open list:HID CORE LAYER, LKML,
bpf, Network Development, sched-ext, linux-rdma, linux-s390,
open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
linux-arm-kernel, Martin KaFai Lau, Chris Mason, Ihor Solodrai
In-Reply-To: <CADUfDZpSSikiZ8d8eWvfucj=Cvhc=k-sHN03EVExGBQ4Lx+23Q@mail.gmail.com>
On Wed, Dec 31, 2025 at 10:09 AM Caleb Sander Mateos
<csander@purestorage.com> wrote:
>
> On Wed, Dec 31, 2025 at 10:04 AM <bot+bpf-ci@kernel.org> wrote:
> >
> > > diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > index 90c4b1a51de6..5e460b1dbdb6 100644
> > > --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> > > +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
> >
> > [ ... ]
> >
> > > @@ -1275,7 +1275,7 @@ bpf_testmod_ops__test_return_ref_kptr(int dummy, struct task_struct *task__ref,
> > > return NULL;
> > > }
> > >
> > > -static struct bpf_testmod_ops __bpf_testmod_ops = {
> > > +static const struct bpf_testmod_ops __bpf_testmod_ops = {
> > > .test_1 = bpf_testmod_test_1,
> > > .test_2 = bpf_testmod_test_2,
> >
> > Is it safe to make __bpf_testmod_ops const here? In bpf_testmod_init(),
> > this struct is modified at runtime:
> >
> > tramp = (void **)&__bpf_testmod_ops.tramp_1;
> > while (tramp <= (void **)&__bpf_testmod_ops.tramp_40)
> > *tramp++ = bpf_testmod_tramp;
> >
> > Writing to a const-qualified object is undefined behavior and may cause a
> > protection fault when the compiler places this in read-only memory. Would
> > the module fail to load on systems where .rodata is actually read-only?
>
> Yup, that's indeed the bug caught by KASAN. Missed this mutation at
> init time, I'll leave __bpf_testmod_ops as mutable.
No. You're missing the point. The whole patch set is no go.
The pointer to cfi stub can be updated just as well.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox