* [STABLE v5.10 1/5] HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration
[not found] <20261109133911.3026622-1-lee@kernel.org>
@ 2026-11-09 13:39 ` Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 2/5] HID: wacom: Fix Use-After-Free in wacom_intuos_pad Lee Jones
` (3 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-11-09 13:39 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, Aaron Skomra, Ping Cheng,
linux-input, linux-kernel
Cc: stable, Jiri Kosina
[ Upstream commit ba16e5ffbaa10fde960918d69af5e49f2b3fdd5e ]
Input subsystem guidelines require that device capabilities are advertised
before the input device is registered. The Wacom driver was violating
this by advertising the SW_MUTE_DEVICE capability post-registration in
wacom_set_shared_values() (and duplicating it in device-specific setup
cases).
Resolve this by moving the SW_MUTE_DEVICE capability setup to
wacom_setup_touch_input_capabilities() for all touch devices that support
it.
For generic touch devices whose capabilities depend on mute switch
usages parsed from a sibling Pen/Pad interface, defer registration
with -EPROBE_DEFER until the sibling has parsed its descriptors and
initialized shared capabilities.
Cc: stable@vger.kernel.org
Fixes: d2ec58aee8b1 ("HID: wacom: generic: support generic touch switch")
Signed-off-by: Lee Jones <lee@kernel.org>
Acked-by: Ping Cheng <ping.cheng@wacom.com>
Tested-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Retain devm_add_action() error handling and adapt context around
is_soft_touch_switch and wacom_initialize_battery()]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/wacom_sys.c | 86 ++++++++++++++++++++++++++++++++++-------
drivers/hid/wacom_wac.c | 5 +++
2 files changed, 77 insertions(+), 14 deletions(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index f418efa868ee..e5d12683f578 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -924,6 +924,9 @@ static int wacom_add_shared_data(struct hid_device *hdev)
wacom_wac->shared = &data->shared;
+ if (wacom_wac->has_mute_touch_switch)
+ WRITE_ONCE(wacom_wac->shared->has_mute_touch_switch, true);
+
retval = devm_add_action(&hdev->dev, wacom_remove_shared_data, wacom);
if (retval) {
mutex_unlock(&wacom_udev_list_lock);
@@ -931,11 +934,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)
return retval;
}
- if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
- wacom_wac->shared->touch = hdev;
- else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
- wacom_wac->shared->pen = hdev;
-
out:
mutex_unlock(&wacom_udev_list_lock);
return retval;
@@ -2336,22 +2334,76 @@ static void wacom_release_resources(struct wacom *wacom)
static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
{
+ struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+
+ guard(mutex)(&wacom_udev_list_lock);
+
+ if (wacom_wac->has_mute_touch_switch) {
+ WRITE_ONCE(wacom_wac->shared->has_mute_touch_switch, true);
+ wacom_wac->shared->is_touch_on = true;
+ }
+
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
wacom_wac->shared->type = wacom_wac->features.type;
wacom_wac->shared->touch_input = wacom_wac->touch_input;
+ wacom_wac->shared->touch = wacom->hdev;
+ } else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) {
+ /* Pairs with smp_load_acquire() in wacom_sibling_pending() */
+ smp_store_release(&wacom_wac->shared->pen, wacom->hdev);
}
+}
- if (wacom_wac->has_mute_touch_switch) {
- wacom_wac->shared->has_mute_touch_switch = true;
- wacom_wac->shared->is_touch_on = true;
- }
+static bool wacom_sibling_pending(struct wacom *wacom)
+{
+ const struct wacom_features *features = &wacom->wacom_wac.features;
+ struct hid_device *hdev = wacom->hdev;
+ struct usb_interface *sibling_intf;
+ int ifnum;
+
+ if (features->type != HID_GENERIC ||
+ !(features->device_type & WACOM_DEVICETYPE_TOUCH))
+ return false;
- if (wacom_wac->shared->has_mute_touch_switch &&
- wacom_wac->shared->touch_input) {
- set_bit(EV_SW, wacom_wac->shared->touch_input->evbit);
- input_set_capability(wacom_wac->shared->touch_input, EV_SW,
- SW_MUTE_DEVICE);
+ if (wacom->wacom_wac.shared) {
+ /* Pairs with smp_store_release() in wacom_set_shared_values() */
+ if (smp_load_acquire(&wacom->wacom_wac.shared->pen))
+ return false;
}
+
+ if (!hid_is_usb(hdev) || !wacom->usbdev || !wacom->intf ||
+ !wacom->intf->cur_altsetting)
+ return false;
+
+ ifnum = wacom->intf->cur_altsetting->desc.bInterfaceNumber;
+
+ /*
+ * On composite Wacom devices, the Pen interface is always interface 0.
+ * If the Touch interface is interface 0, there is no sibling Pen
+ * interface on this device (standalone touch device).
+ */
+ if (ifnum == 0)
+ return false;
+
+ /* Look for the sibling Pen interface at interface 0 */
+ sibling_intf = usb_ifnum_to_if(wacom->usbdev, 0);
+ if (!sibling_intf || !sibling_intf->cur_altsetting)
+ return false;
+
+ if (sibling_intf->cur_altsetting->desc.bInterfaceClass !=
+ USB_INTERFACE_CLASS_HID)
+ return false;
+
+ if (sibling_intf->cur_altsetting->desc.bInterfaceSubClass == 1 &&
+ (sibling_intf->cur_altsetting->desc.bInterfaceProtocol == 1 ||
+ sibling_intf->cur_altsetting->desc.bInterfaceProtocol == 2))
+ return false;
+
+ /*
+ * Interface 0 is a candidate HID interface on this composite device
+ * whose probe has not completed yet (shared->pen is NULL). Defer until
+ * interface 0 finishes probing and registers shared values.
+ */
+ return true;
}
static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
@@ -2427,6 +2479,11 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
if (error)
goto fail;
+ if (wacom_sibling_pending(wacom)) {
+ error = -EPROBE_DEFER;
+ goto fail;
+ }
+
if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
(features->quirks & WACOM_QUIRK_BATTERY)) {
error = wacom_initialize_battery(wacom);
@@ -2491,6 +2548,7 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
fail_hw_stop:
hid_hw_stop(hdev);
+ cancel_delayed_work_sync(&wacom->init_work);
fail:
wacom_release_resources(wacom);
return error;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index f74da953d78f..8804bc2cba32 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3882,6 +3882,11 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
if (features->type == HID_GENERIC) {
hid_dbg(hdev, "generic touch setup\n");
+ if (wacom_wac->has_mute_touch_switch ||
+ (wacom_wac->shared && READ_ONCE(wacom_wac->shared->has_mute_touch_switch))) {
+ input_set_capability(input_dev, EV_SW, SW_MUTE_DEVICE);
+ wacom_wac->has_mute_touch_switch = true;
+ }
/* setup has already been done */
return 0;
}
--
2.56.0.506.g506a7eabc5-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [STABLE v5.10 2/5] HID: wacom: Fix Use-After-Free in wacom_intuos_pad
[not found] <20261109133911.3026622-1-lee@kernel.org>
2026-11-09 13:39 ` [STABLE v5.10 1/5] HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration Lee Jones
@ 2026-11-09 13:39 ` Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 3/5] HID: wacom: Fix Use-After-Free in wacom_bamboo_pad Lee Jones
` (2 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-11-09 13:39 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, Ping Cheng,
Dmitry Torokhov, Peter Hutterer, linux-input, linux-kernel
Cc: stable, Jiri Kosina
[ Upstream commit ef32877368a7013c060ef6bd03a30b6da2fe0c41 ]
wacom_intuos_pad() accesses wacom->shared->touch_input locklessly
inside the interrupt handler context. If the Touch sibling device
is disconnected, wacom_remove_shared_data() clears 'touch_input'
outside any lock, creating a Time-of-Check to Time-of-Use (TOCTOU)
race condition where a preempted reader in interrupt context
dereferences the freed pointer, leading to a Use-After-Free.
Resolve this by introducing RCU protection for the touch_input
pointer:
- Annotate 'touch_input' in wacom_shared struct with __rcu
- Wrap all lockless readers in wacom_wac.c with guard(rcu)() and
rcu_dereference() using a unified wacom_report_touch_mute()
helper
- Update writers in wacom_sys.c using rcu_assign_pointer()
- Call synchronize_rcu() in wacom_remove_shared_data() to ensure
all active RCU readers have finished before the input device is
freed
Also wrap wacom_set_shared_values() and touch/pen assignments in
wacom_add_shared_data() inside the wacom_udev_list_lock to serialize
concurrent probe assignments, and verify that 'shared->touch == hdev'
before setting touch_input to prevent concurrent sibling probe state
desynchronization.
Cc: stable@vger.kernel.org
Fixes: 961794a00eab ("Input: wacom - add reporting of SW_MUTE_DEVICE events")
Signed-off-by: Lee Jones <lee@kernel.org>
Acked-by: Ping Cheng <ping.cheng@wacom.com>
Tested-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Use explicit mutex_lock()/mutex_unlock() in wacom_remove_shared_data()
for -std=gnu89 compatibility and adapt to res_wacom]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/wacom_sys.c | 18 +++++++++++++-----
drivers/hid/wacom_wac.c | 36 ++++++++++++++++++------------------
drivers/hid/wacom_wac.h | 2 +-
3 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index e5d12683f578..94e12c56e040 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -885,10 +885,16 @@ static void wacom_remove_shared_data(void *res)
data = container_of(wacom_wac->shared, struct wacom_hdev_data,
shared);
- if (wacom_wac->shared->touch == res_wacom->hdev)
+ mutex_lock(&wacom_udev_list_lock);
+ if (wacom_wac->shared->touch == res_wacom->hdev) {
wacom_wac->shared->touch = NULL;
- else if (wacom_wac->shared->pen == res_wacom->hdev)
+ rcu_assign_pointer(wacom_wac->shared->touch_input, NULL);
+ } else if (wacom_wac->shared->pen == res_wacom->hdev) {
wacom_wac->shared->pen = NULL;
+ }
+ mutex_unlock(&wacom_udev_list_lock);
+
+ synchronize_rcu();
if (kref_put_mutex(&data->kref, wacom_release_shared_data, &wacom_udev_list_lock))
mutex_unlock(&wacom_udev_list_lock);
@@ -2344,9 +2350,11 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
}
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
- wacom_wac->shared->type = wacom_wac->features.type;
- wacom_wac->shared->touch_input = wacom_wac->touch_input;
- wacom_wac->shared->touch = wacom->hdev;
+ if (wacom_wac->shared->touch == wacom->hdev || !wacom_wac->shared->touch) {
+ wacom_wac->shared->type = wacom_wac->features.type;
+ wacom_wac->shared->touch = wacom->hdev;
+ rcu_assign_pointer(wacom_wac->shared->touch_input, wacom_wac->touch_input);
+ }
} else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) {
/* Pairs with smp_load_acquire() in wacom_sibling_pending() */
smp_store_release(&wacom_wac->shared->pen, wacom->hdev);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 8804bc2cba32..059572ea0509 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -510,6 +510,18 @@ static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
}
}
+static void wacom_report_touch_mute(struct wacom_wac *wacom_wac, bool mute)
+{
+ struct input_dev *touch_input;
+
+ guard(rcu)();
+ touch_input = rcu_dereference(wacom_wac->shared->touch_input);
+ if (touch_input) {
+ input_report_switch(touch_input, SW_MUTE_DEVICE, mute);
+ input_sync(touch_input);
+ }
+}
+
static int wacom_intuos_pad(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
@@ -650,12 +662,8 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
input_report_key(input, KEY_CONTROLPANEL, menu);
input_report_key(input, KEY_INFO, info);
- if (wacom->shared && wacom->shared->touch_input) {
- input_report_switch(wacom->shared->touch_input,
- SW_MUTE_DEVICE,
- !wacom->shared->is_touch_on);
- input_sync(wacom->shared->touch_input);
- }
+ if (wacom->shared)
+ wacom_report_touch_mute(wacom, !wacom->shared->is_touch_on);
input_report_abs(input, ABS_RX, strip1);
input_report_abs(input, ABS_RY, strip2);
@@ -2191,7 +2199,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
*/
if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) ||
(equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) {
- if (wacom_wac->shared->touch_input) {
+ if (wacom_wac->shared) {
bool *is_touch_on = &wacom_wac->shared->is_touch_on;
if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
@@ -2199,9 +2207,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
*is_touch_on = value;
- input_report_switch(wacom_wac->shared->touch_input,
- SW_MUTE_DEVICE, !(*is_touch_on));
- input_sync(wacom_wac->shared->touch_input);
+ wacom_report_touch_mute(wacom_wac, !(*is_touch_on));
}
return;
}
@@ -3292,11 +3298,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
if ((wacom->shared->type == INTUOSHT ||
wacom->shared->type == INTUOSHT2) &&
- wacom->shared->touch_input &&
wacom->shared->touch_max) {
- input_report_switch(wacom->shared->touch_input,
- SW_MUTE_DEVICE, data[5] & 0x40);
- input_sync(wacom->shared->touch_input);
+ wacom_report_touch_mute(wacom, data[5] & 0x40);
}
pid = get_unaligned_be16(&data[6]);
@@ -3331,11 +3334,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
if ((features->type == INTUOSHT ||
features->type == INTUOSHT2) &&
- wacom_wac->shared->touch_input &&
features->touch_max) {
- input_report_switch(wacom_wac->shared->touch_input,
- SW_MUTE_DEVICE, data[8] & 0x40);
- input_sync(wacom_wac->shared->touch_input);
+ wacom_report_touch_mute(wacom_wac, data[8] & 0x40);
}
if (data[9] & 0x02) { /* wireless module is attached */
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 0de34c13e7a1..957247e6ba1c 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -286,7 +286,7 @@ struct wacom_shared {
/* for wireless device to access USB interfaces */
unsigned touch_max;
int type;
- struct input_dev *touch_input;
+ struct input_dev __rcu *touch_input;
struct hid_device *pen;
struct hid_device *touch;
bool has_mute_touch_switch;
--
2.56.0.506.g506a7eabc5-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [STABLE v5.10 3/5] HID: wacom: Fix Use-After-Free in wacom_bamboo_pad
[not found] <20261109133911.3026622-1-lee@kernel.org>
2026-11-09 13:39 ` [STABLE v5.10 1/5] HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 2/5] HID: wacom: Fix Use-After-Free in wacom_intuos_pad Lee Jones
@ 2026-11-09 13:39 ` Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 4/5] HID: wacom: Write shared touch initial status only once Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 5/5] HID: wacom: Setup SW_MUTE_DEVICE according to the order of input registration Lee Jones
4 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-11-09 13:39 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, Ping Cheng, linux-input,
linux-kernel
Cc: stable, Jiri Kosina
[ Upstream commit 3a523ecf9ac3fdd33f5eb31c43937ee44135395b ]
wacom_bamboo_pad_pen_event() accesses wacom->shared->pen locklessly
relative to wacom_remove_shared_data() which nullifies it. This
can lead to a Use-After-Free if the sibling device is removed while
events are being processed.
Resolve this by introducing RCU protection for pen and touch
pointers:
- Annotate 'pen' and 'touch' in wacom_shared struct with __rcu.
- Wrap lockless readers in wacom_bamboo_pad_pen_event() with
rcu_read_lock() and rcu_dereference().
- Update writers in wacom_sys.c using rcu_assign_pointer().
- Use rcu_dereference_protected for comparisons under
wacom_udev_list_lock.
- Also use rcu_access_pointer in wacom_sibling_pending() and
wacom_mode_change_work() to avoid warnings (while lockless access in
the latter remains a pre-existing issue).
Cc: stable@vger.kernel.org
Fixes: 8c97a765467c ("HID: wacom: add full support of the Wacom Bamboo PAD")
Signed-off-by: Lee Jones <lee@kernel.org>
Acked-by: Ping Cheng <ping.cheng@wacom.com>
Tested-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Use explicit lock/unlock calls and top-of-block declarations in
wacom_remove_shared_data() and wacom_bamboo_pad_pen_event() for
-std=gnu89 compatibility, and adapt to res_wacom]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/wacom_sys.c | 40 ++++++++++++++++++++++++++--------------
drivers/hid/wacom_wac.c | 14 +++++++-------
drivers/hid/wacom_wac.h | 4 ++--
3 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 94e12c56e040..465d075d16f9 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -882,15 +882,22 @@ static void wacom_remove_shared_data(void *res)
struct wacom_wac *wacom_wac = &res_wacom->wacom_wac;
if (wacom_wac->shared) {
+ struct hid_device *touch, *pen;
+
data = container_of(wacom_wac->shared, struct wacom_hdev_data,
shared);
mutex_lock(&wacom_udev_list_lock);
- if (wacom_wac->shared->touch == res_wacom->hdev) {
- wacom_wac->shared->touch = NULL;
+ touch = rcu_dereference_protected(wacom_wac->shared->touch,
+ lockdep_is_held(&wacom_udev_list_lock));
+ pen = rcu_dereference_protected(wacom_wac->shared->pen,
+ lockdep_is_held(&wacom_udev_list_lock));
+
+ if (touch == res_wacom->hdev) {
+ rcu_assign_pointer(wacom_wac->shared->touch, NULL);
rcu_assign_pointer(wacom_wac->shared->touch_input, NULL);
- } else if (wacom_wac->shared->pen == res_wacom->hdev) {
- wacom_wac->shared->pen = NULL;
+ } else if (pen == res_wacom->hdev) {
+ rcu_assign_pointer(wacom_wac->shared->pen, NULL);
}
mutex_unlock(&wacom_udev_list_lock);
@@ -2350,14 +2357,17 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
}
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
- if (wacom_wac->shared->touch == wacom->hdev || !wacom_wac->shared->touch) {
+ struct hid_device *touch =
+ rcu_dereference_protected(wacom_wac->shared->touch,
+ lockdep_is_held(&wacom_udev_list_lock));
+
+ if (touch == wacom->hdev || !touch) {
wacom_wac->shared->type = wacom_wac->features.type;
- wacom_wac->shared->touch = wacom->hdev;
+ rcu_assign_pointer(wacom_wac->shared->touch, wacom->hdev);
rcu_assign_pointer(wacom_wac->shared->touch_input, wacom_wac->touch_input);
}
} else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) {
- /* Pairs with smp_load_acquire() in wacom_sibling_pending() */
- smp_store_release(&wacom_wac->shared->pen, wacom->hdev);
+ rcu_assign_pointer(wacom_wac->shared->pen, wacom->hdev);
}
}
@@ -2373,8 +2383,7 @@ static bool wacom_sibling_pending(struct wacom *wacom)
return false;
if (wacom->wacom_wac.shared) {
- /* Pairs with smp_store_release() in wacom_set_shared_values() */
- if (smp_load_acquire(&wacom->wacom_wac.shared->pen))
+ if (rcu_access_pointer(wacom->wacom_wac.shared->pen))
return false;
}
@@ -2844,16 +2853,19 @@ static void wacom_mode_change_work(struct work_struct *work)
bool is_direct = wacom->wacom_wac.is_direct_mode;
int error = 0;
- if (shared->pen) {
- wacom1 = hid_get_drvdata(shared->pen);
+ struct hid_device *pen = rcu_access_pointer(shared->pen);
+ struct hid_device *touch = rcu_access_pointer(shared->touch);
+
+ if (pen) {
+ wacom1 = hid_get_drvdata(pen);
wacom_release_resources(wacom1);
hid_hw_stop(wacom1->hdev);
wacom1->wacom_wac.has_mode_change = true;
wacom1->wacom_wac.is_direct_mode = is_direct;
}
- if (shared->touch) {
- wacom2 = hid_get_drvdata(shared->touch);
+ if (touch) {
+ wacom2 = hid_get_drvdata(touch);
wacom_release_resources(wacom2);
hid_hw_stop(wacom2->hdev);
wacom2->wacom_wac.has_mode_change = true;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 059572ea0509..4c7ad9dc543e 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3203,6 +3203,7 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
unsigned char *data)
{
+ struct hid_device *pen;
unsigned char prefix;
/*
@@ -3215,13 +3216,12 @@ static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom,
prefix = data[0];
data[0] = WACOM_REPORT_BPAD_PEN;
- /*
- * actually reroute the event.
- * No need to check if wacom->shared->pen is valid, hid_input_report()
- * will check for us.
- */
- hid_input_report(wacom->shared->pen, HID_INPUT_REPORT, data,
- WACOM_PKGLEN_PENABLED, 1);
+ rcu_read_lock();
+ pen = rcu_dereference(wacom->shared->pen);
+ if (pen)
+ hid_input_report(pen, HID_INPUT_REPORT, data,
+ WACOM_PKGLEN_PENABLED, 1);
+ rcu_read_unlock();
data[0] = prefix;
}
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 957247e6ba1c..56d54ac53b3d 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -287,8 +287,8 @@ struct wacom_shared {
unsigned touch_max;
int type;
struct input_dev __rcu *touch_input;
- struct hid_device *pen;
- struct hid_device *touch;
+ struct hid_device __rcu *pen;
+ struct hid_device __rcu *touch;
bool has_mute_touch_switch;
bool is_touch_on;
};
--
2.56.0.506.g506a7eabc5-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [STABLE v5.10 4/5] HID: wacom: Write shared touch initial status only once
[not found] <20261109133911.3026622-1-lee@kernel.org>
` (2 preceding siblings ...)
2026-11-09 13:39 ` [STABLE v5.10 3/5] HID: wacom: Fix Use-After-Free in wacom_bamboo_pad Lee Jones
@ 2026-11-09 13:39 ` Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 5/5] HID: wacom: Setup SW_MUTE_DEVICE according to the order of input registration Lee Jones
4 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-11-09 13:39 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, Ping Cheng, linux-input,
linux-kernel
Cc: stable, Jiri Kosina
From: Ping Cheng <ping.cheng@wacom.com>
[ Upstream commit cae3031c691dff0be61a26bc64e31a6939010d5c ]
For consistency with how the shared has_mute_touch_switch is handled
during registration, let's apply WRITE_ONCE to is_touch_on too.
Cc: stable@vger.kernel.org
Fixes: ba16e5ffbaa1 ("HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration")
Reviewed-by: Lee Jones <lee@kernel.org>
Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
[Lee: Resolve context conflict around is_soft_touch_switch in
wacom_set_shared_values()]
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/wacom_sys.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 465d075d16f9..ad570af50745 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2353,7 +2353,7 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
if (wacom_wac->has_mute_touch_switch) {
WRITE_ONCE(wacom_wac->shared->has_mute_touch_switch, true);
- wacom_wac->shared->is_touch_on = true;
+ WRITE_ONCE(wacom_wac->shared->is_touch_on, true);
}
if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
--
2.56.0.506.g506a7eabc5-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [STABLE v5.10 5/5] HID: wacom: Setup SW_MUTE_DEVICE according to the order of input registration
[not found] <20261109133911.3026622-1-lee@kernel.org>
` (3 preceding siblings ...)
2026-11-09 13:39 ` [STABLE v5.10 4/5] HID: wacom: Write shared touch initial status only once Lee Jones
@ 2026-11-09 13:39 ` Lee Jones
4 siblings, 0 replies; 5+ messages in thread
From: Lee Jones @ 2026-11-09 13:39 UTC (permalink / raw)
To: lee, Jiri Kosina, Benjamin Tissoires, Ping Cheng, linux-input,
linux-kernel
Cc: stable, Jiri Kosina
From: Ping Cheng <ping.cheng@wacom.com>
[ Upstream commit 97ce491bcef2d231b8d51cee8e579183319a5ba4 ]
The refactored SW_MUTE_DEVICE code assumed that stylus will be
the first regiestered input. In reality, touch can be registered
before stylus, such as the Wacom Cintiq Pro 13 and 16.
This patch covers both touch-first and stylus-first cases.
Cc: stable@vger.kernel.org
Fixes: ba16e5ffbaa1 ("HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration")
Reviewed-by: Lee Jones <lee@kernel.org>
Signed-off-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
Signed-off-by: Lee Jones <lee@kernel.org>
---
drivers/hid/wacom_wac.c | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 4c7ad9dc543e..0301f345a024 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3882,10 +3882,18 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
if (features->type == HID_GENERIC) {
hid_dbg(hdev, "generic touch setup\n");
- if (wacom_wac->has_mute_touch_switch ||
- (wacom_wac->shared && READ_ONCE(wacom_wac->shared->has_mute_touch_switch))) {
+
+ /*
+ * This is to setup the touch switch for those devices that report
+ * pen interface first. The setup can only be done here since this
+ * routine is only called once. When we are here, the shared
+ * has_mute_touch_switch has been set by the pad.
+
+ * There are two ways of reporting inputs from firmware: stylus first
+ * or touch first. This path covers the stylus input first case.
+ */
+ if (wacom_wac->shared && READ_ONCE(wacom_wac->shared->has_mute_touch_switch)) {
input_set_capability(input_dev, EV_SW, SW_MUTE_DEVICE);
- wacom_wac->has_mute_touch_switch = true;
}
/* setup has already been done */
return 0;
@@ -4307,7 +4315,26 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
break;
case INTUOSHT3_BT:
+ break;
+
case HID_GENERIC:
+ if (wacom_wac->shared) {
+ /*
+ * The setup of touch switch capability can only be done
+ * here for those devices, such as Cintiq Pro 13 and 16,
+ * that have touch input registered before stylus and pad
+ * inputs.
+ *
+ * There are two ways of reporting inputs from firmware:
+ * stylus first or touch first. This path covers the touch
+ * input first case.
+ */
+ if (wacom_wac->has_mute_touch_switch &&
+ wacom_wac->shared->touch_input) {
+ input_set_capability(wacom_wac->shared->touch_input,
+ EV_SW, SW_MUTE_DEVICE);
+ }
+ }
break;
default:
--
2.56.0.506.g506a7eabc5-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-09 13:39 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20261109133911.3026622-1-lee@kernel.org>
2026-11-09 13:39 ` [STABLE v5.10 1/5] HID: wacom: Advertise SW_MUTE_DEVICE capability prior to registration Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 2/5] HID: wacom: Fix Use-After-Free in wacom_intuos_pad Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 3/5] HID: wacom: Fix Use-After-Free in wacom_bamboo_pad Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 4/5] HID: wacom: Write shared touch initial status only once Lee Jones
2026-11-09 13:39 ` [STABLE v5.10 5/5] HID: wacom: Setup SW_MUTE_DEVICE according to the order of input registration Lee Jones
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®