* [PATCH v11 0/2] HID: multitouch: fix haptic lifetime on delayed input release
@ 2026-10-17 16:41 Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 1/2] HID: haptic: make FF creation the last fallible init step Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 2/2] HID: multitouch: give FF core ownership of haptic state Aldo Ariel Panzardo
0 siblings, 2 replies; 3+ messages in thread
From: Aldo Ariel Panzardo @ 2026-10-17 16:41 UTC (permalink / raw)
To: jikos, bentiss
Cc: dmitry.torokhov, linux-input, linux-kernel, stable,
Aldo Ariel Panzardo
v10 review found that the multitouch slot setup ran before validating
the haptic class and selecting the input that owns FF. This could set
INPUT_MT_TOTAL_FORCE on an input without haptics. If no multitouch
touchpad input was found, haptic mode could remain enabled.
Patch 2 now validates the class and attaches FF before setting up MT
slots. It selects the input where multitouch touchpad pressure was
mapped with gram or newton units, so an earlier multitouch report
without haptic pressure cannot take the sole FF instance. Only that
input gets pointer emulation, total force and haptic pressure
accounting. Haptic mode is disabled if no input receives FF. Patch 1
is unchanged from v10.
Tested on x86_64 with W=1. The HID multitouch module compiled, and
QEMU/KVM with KASAN completed 10 virtual UHID haptic cycles and 10
multi-input cycles with a non-multitouch report before the multitouch
report. The tests checked FF_HAPTIC, effect upload and playback, HID
removal with an open evdev fd, and final release. Two negative fixtures
had gram pressure but either no haptic reports or no touchpad report.
With two contacts, v10 summed ABS_PRESSURE to 30 in both cases; v11
reported the oldest contact's pressure of 10. A split-report fixture
placed a multitouch report without pressure before the pressure-bearing
one; FF, INPUT_PROP_POINTER and ABS_PRESSURE were on the latter input.
No KASAN report was emitted. Physical hardware was not tested.
Base: 58161ead29e50d70a317ea26b472e0c7508e69da
v9: https://lore.kernel.org/linux-input/20261017140332.1480375-1-qwe.aldo@gmail.com/
Aldo Ariel Panzardo (2):
HID: haptic: make FF creation the last fallible init step
HID: multitouch: give FF core ownership of haptic state
drivers/hid/hid-haptic.c | 161 +++++++++++++++++------------------
drivers/hid/hid-haptic.h | 6 +-
drivers/hid/hid-multitouch.c | 59 ++++++++++---
3 files changed, 125 insertions(+), 101 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v11 1/2] HID: haptic: make FF creation the last fallible init step
2026-10-17 16:41 [PATCH v11 0/2] HID: multitouch: fix haptic lifetime on delayed input release Aldo Ariel Panzardo
@ 2026-10-17 16:41 ` Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 2/2] HID: multitouch: give FF core ownership of haptic state Aldo Ariel Panzardo
1 sibling, 0 replies; 3+ messages in thread
From: Aldo Ariel Panzardo @ 2026-10-17 16:41 UTC (permalink / raw)
To: jikos, bentiss
Cc: dmitry.torokhov, linux-input, linux-kernel, stable,
Aldo Ariel Panzardo
The caller holds the module while setting up the device. Use
__module_get() after input_ff_create() succeeds, leaving no fallible
step after the FF callbacks are installed.
Drain haptic work through ff->stop when the input device is
unregistered, before it drops its parent reference. The destroy
callback also drains work for devices that were never registered.
After unregistration, that callback only frees local allocations, so
remove the extra HID device reference and its error path.
Clear the FF capability bits if input_ff_create() fails. Return the
error from hid_haptic_input_configured() and save it in the multitouch
driver. Probe must fail even if hidraw lets hid_connect() succeed after
hidinput_connect() has unwound.
Fixes: 8d0bf7908b5a ("HID: multitouch: add haptic multitouch support")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---
drivers/hid/hid-haptic.c | 48 ++++++++++++++----------------------
drivers/hid/hid-multitouch.c | 18 ++++++++++++--
2 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c
index 8760eeb..0a6126e 100644
--- a/drivers/hid/hid-haptic.c
+++ b/drivers/hid/hid-haptic.c
@@ -96,7 +96,7 @@ int hid_haptic_input_configured(struct hid_device *hdev,
if (error) {
dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n",
hdev->name);
- return 0;
+ return error;
}
return 1;
@@ -377,14 +377,22 @@ static int hid_haptic_erase(struct input_dev *dev, int effect_id)
return 0;
}
+static void hid_haptic_stop(struct ff_device *ff)
+{
+ struct hid_haptic_device *haptic = ff->private;
+
+ if (haptic->wq) {
+ destroy_workqueue(haptic->wq);
+ haptic->wq = NULL;
+ }
+}
+
static void hid_haptic_destroy(struct ff_device *ff)
{
struct hid_haptic_device *haptic = ff->private;
- struct hid_device *hdev = haptic->hdev;
int r;
- if (hdev)
- put_device(&hdev->dev);
+ hid_haptic_stop(ff);
kfree(haptic->stop_effect.report_buf);
haptic->stop_effect.report_buf = NULL;
@@ -396,9 +404,6 @@ static void hid_haptic_destroy(struct ff_device *ff)
}
haptic->effect = NULL;
- destroy_workqueue(haptic->wq);
- haptic->wq = NULL;
-
kfree(haptic->duration_map);
haptic->duration_map = NULL;
@@ -419,8 +424,6 @@ int hid_haptic_init(struct hid_device *hdev,
};
const char *prefix = "hid-haptic";
char *name;
- int (*flush)(struct input_dev *dev, struct file *file);
- int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
haptic->hdev = hdev;
haptic->max_waveform_id = max(2u, haptic->max_waveform_id);
@@ -501,38 +504,25 @@ int hid_haptic_init(struct hid_device *hdev,
input_set_capability(dev, EV_FF, FF_HAPTIC);
- flush = dev->flush;
- event = dev->event;
ret = input_ff_create(dev, FF_MAX_EFFECTS);
if (ret) {
dev_err(&hdev->dev, "Failed to create ff device.\n");
- goto stop_buffer_free;
+ goto ff_cap_clear;
}
ff = dev->ff;
- ff->private = haptic;
ff->upload = hid_haptic_upload_effect;
ff->playback = hid_haptic_playback;
ff->erase = hid_haptic_erase;
+ ff->stop = hid_haptic_stop;
ff->destroy = hid_haptic_destroy;
- if (!try_module_get(THIS_MODULE)) {
- dev_err(&hdev->dev, "Failed to increase module count.\n");
- goto input_free;
- }
- if (!get_device(&hdev->dev)) {
- dev_err(&hdev->dev, "Failed to get hdev device.\n");
- module_put(THIS_MODULE);
- goto input_free;
- }
+ __module_get(THIS_MODULE);
+ ff->private = haptic;
return 0;
-input_free:
- input_ff_destroy(dev);
- /* Restore dev flush and event */
- dev->flush = flush;
- dev->event = event;
- return ret;
-stop_buffer_free:
+ff_cap_clear:
+ __clear_bit(FF_HAPTIC, dev->ffbit);
+ __clear_bit(EV_FF, dev->evbit);
kfree(haptic->stop_effect.report_buf);
haptic->stop_effect.report_buf = NULL;
buffer_free:
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 4e19a0c..154dc94 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -174,6 +174,7 @@ struct mt_device {
struct mt_class mtclass; /* our mt device class */
struct timer_list release_timer; /* to release sticky fingers */
struct hid_haptic_device *haptic; /* haptic related configuration */
+ int haptic_init_error;
struct hid_device *hdev; /* hid_device we're attached to */
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_RUNNING) */
unsigned long *active_slots; /* bitmap of slots with an active
@@ -1958,8 +1959,16 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) {
- if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
- td->is_haptic_touchpad = false;
+ if (hi->application == HID_DG_TOUCHPAD) {
+ ret = hid_haptic_input_configured(hdev, td->haptic, hi);
+ if (ret < 0) {
+ td->haptic_init_error = ret;
+ td->is_haptic_touchpad = false;
+ return ret;
+ }
+ if (ret == 0)
+ td->is_haptic_touchpad = false;
+ }
} else {
td->is_haptic_touchpad = false;
}
@@ -2197,6 +2206,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret)
return ret;
+ if (td->haptic_init_error) {
+ ret = td->haptic_init_error;
+ hid_hw_stop(hdev);
+ return ret;
+ }
ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v11 2/2] HID: multitouch: give FF core ownership of haptic state
2026-10-17 16:41 [PATCH v11 0/2] HID: multitouch: fix haptic lifetime on delayed input release Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 1/2] HID: haptic: make FF creation the last fallible init step Aldo Ariel Panzardo
@ 2026-10-17 16:41 ` Aldo Ariel Panzardo
1 sibling, 0 replies; 3+ messages in thread
From: Aldo Ariel Panzardo @ 2026-10-17 16:41 UTC (permalink / raw)
To: jikos, bentiss
Cc: dmitry.torokhov, linux-input, linux-kernel, stable,
Aldo Ariel Panzardo
An open evdev fd can delay input_ff_destroy() until after HID unbind.
The descriptor mapping state is devres managed and cannot serve as
ff->private for that lifetime.
Clone the mapped state in hid_haptic_init(). Transfer the allocation
to ff->private only after input_ff_create() succeeds; the input core
then frees it at final input device release. Scope cleanup releases
the clone and its subresources on initialization failure.
On devices with multiple inputs, attach FF to the multitouch touchpad
input whose pressure uses gram or newton units. An earlier touchpad
report without a multitouch collection or haptic pressure must not
consume the single FF instance. Other inputs skip FF initialization
and do not acquire INPUT_PROP_PRESSUREPAD from the haptic setup. The
HID reports are shared, so multiple FF instances would write the same
fields under different mutexes.
Validate the touchpad class and initialize FF before setting up MT
slots. Enable pointer emulation, total force and contact pressure
accounting on the input that owns FF. If no input receives FF, disable
haptic mode before input reports can be processed.
Fixes: 8d0bf7908b5a ("HID: multitouch: add haptic multitouch support")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---
drivers/hid/hid-haptic.c | 131 ++++++++++++++++++-----------------
drivers/hid/hid-haptic.h | 6 +-
drivers/hid/hid-multitouch.c | 61 ++++++++++------
3 files changed, 109 insertions(+), 89 deletions(-)
diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c
index 0a6126e..ec2a891 100644
--- a/drivers/hid/hid-haptic.c
+++ b/drivers/hid/hid-haptic.c
@@ -5,6 +5,7 @@
* Copyright (c) 2021 Angela Czubak <acz@semihalf.com>
*/
+#include <linux/cleanup.h>
#include <linux/input/mt.h>
#include <linux/module.h>
@@ -90,7 +91,9 @@ int hid_haptic_input_configured(struct hid_device *hdev,
if (!haptic->auto_trigger_report || !haptic->manual_trigger_report)
return 0;
- __set_bit(INPUT_PROP_PRESSUREPAD, hi->input->propbit);
+ /* The HID reports are shared; create only one FF instance. */
+ if (haptic->input_dev)
+ return 1;
error = hid_haptic_init(hdev, haptic, hi->input);
if (error) {
@@ -99,6 +102,9 @@ int hid_haptic_input_configured(struct hid_device *hdev,
return error;
}
+ __set_bit(INPUT_PROP_PRESSUREPAD, hi->input->propbit);
+ haptic->input_dev = hi->input;
+
return 1;
}
EXPORT_SYMBOL_GPL(hid_haptic_input_configured);
@@ -377,53 +383,76 @@ static int hid_haptic_erase(struct input_dev *dev, int effect_id)
return 0;
}
-static void hid_haptic_stop(struct ff_device *ff)
+static void hid_haptic_stop_work(struct hid_haptic_device *haptic)
{
- struct hid_haptic_device *haptic = ff->private;
-
if (haptic->wq) {
destroy_workqueue(haptic->wq);
haptic->wq = NULL;
}
}
-static void hid_haptic_destroy(struct ff_device *ff)
+static void hid_haptic_stop(struct ff_device *ff)
+{
+ hid_haptic_stop_work(ff->private);
+}
+
+static void hid_haptic_free_resources(struct hid_haptic_device *haptic)
{
- struct hid_haptic_device *haptic = ff->private;
int r;
- hid_haptic_stop(ff);
+ hid_haptic_stop_work(haptic);
kfree(haptic->stop_effect.report_buf);
- haptic->stop_effect.report_buf = NULL;
if (haptic->effect) {
- for (r = 0; r < ff->max_effects; r++)
+ for (r = 0; r < FF_MAX_EFFECTS; r++)
kfree(haptic->effect[r].report_buf);
kfree(haptic->effect);
}
- haptic->effect = NULL;
kfree(haptic->duration_map);
- haptic->duration_map = NULL;
-
kfree(haptic->hid_usage_map);
- haptic->hid_usage_map = NULL;
+}
+
+static void hid_haptic_free_state(struct hid_haptic_device *haptic)
+{
+ if (haptic) {
+ hid_haptic_free_resources(haptic);
+ kfree(haptic);
+ }
+}
+
+DEFINE_FREE(hid_haptic_state, struct hid_haptic_device *, hid_haptic_free_state(_T));
+
+static void hid_haptic_destroy(struct ff_device *ff)
+{
+ struct hid_haptic_device *haptic = ff->private;
+
+ hid_haptic_free_resources(haptic);
module_put(THIS_MODULE);
}
int hid_haptic_init(struct hid_device *hdev,
- struct hid_haptic_device *haptic,
+ const struct hid_haptic_device *config,
struct input_dev *dev)
{
+ struct hid_haptic_device *haptic __free(hid_haptic_state) =
+ kmemdup(config, sizeof(*config), GFP_KERNEL);
struct ff_device *ff;
- int ret = 0, r;
+ int ret, r;
struct ff_haptic_effect stop_effect = {
.hid_usage = HID_HP_WAVEFORMSTOP & HID_USAGE,
};
- const char *prefix = "hid-haptic";
- char *name;
+ if (!haptic)
+ return -ENOMEM;
+
+ /* The mapping state does not own these allocations. */
+ haptic->hid_usage_map = NULL;
+ haptic->duration_map = NULL;
+ haptic->effect = NULL;
+ haptic->stop_effect.report_buf = NULL;
+ haptic->wq = NULL;
haptic->hdev = hdev;
haptic->max_waveform_id = max(2u, haptic->max_waveform_id);
@@ -431,16 +460,12 @@ int hid_haptic_init(struct hid_device *hdev,
haptic->hid_usage_map = kcalloc(haptic->max_waveform_id + 1,
sizeof(u16), GFP_KERNEL);
- if (!haptic->hid_usage_map) {
- ret = -ENOMEM;
- goto exit;
- }
+ if (!haptic->hid_usage_map)
+ return -ENOMEM;
haptic->duration_map = kcalloc(haptic->max_duration_id + 1,
sizeof(u32), GFP_KERNEL);
- if (!haptic->duration_map) {
- ret = -ENOMEM;
- goto usage_map;
- }
+ if (!haptic->duration_map)
+ return -ENOMEM;
if (haptic->max_waveform_id != haptic->max_duration_id)
dev_warn(&hdev->dev,
@@ -460,21 +485,19 @@ int hid_haptic_init(struct hid_device *hdev,
haptic->manual_trigger_report_len =
hid_report_len(haptic->manual_trigger_report);
mutex_init(&haptic->manual_trigger_mutex);
- name = kmalloc(strlen(prefix) + strlen(hdev->name) + 2, GFP_KERNEL);
- if (name) {
- sprintf(name, "%s %s", prefix, hdev->name);
+ {
+ char *name __free(kfree) = kasprintf(GFP_KERNEL,
+ "hid-haptic %s", hdev->name);
+
+ if (!name)
+ return -ENOMEM;
haptic->wq = create_singlethread_workqueue(name);
- kfree(name);
- }
- if (!haptic->wq) {
- ret = -ENOMEM;
- goto duration_map;
}
+ if (!haptic->wq)
+ return -ENOMEM;
haptic->effect = kzalloc_objs(struct hid_haptic_effect, FF_MAX_EFFECTS);
- if (!haptic->effect) {
- ret = -ENOMEM;
- goto output_queue;
- }
+ if (!haptic->effect)
+ return -ENOMEM;
for (r = 0; r < FF_MAX_EFFECTS; r++) {
haptic->effect[r].report_buf =
hid_alloc_report_buf(haptic->manual_trigger_report,
@@ -482,8 +505,7 @@ int hid_haptic_init(struct hid_device *hdev,
if (!haptic->effect[r].report_buf) {
dev_err(&hdev->dev,
"Failed to allocate a buffer for an effect.\n");
- ret = -ENOMEM;
- goto buffer_free;
+ return -ENOMEM;
}
haptic->effect[r].input_dev = dev;
INIT_WORK(&haptic->effect[r].work, haptic_work_handler);
@@ -494,8 +516,7 @@ int hid_haptic_init(struct hid_device *hdev,
if (!haptic->stop_effect.report_buf) {
dev_err(&hdev->dev,
"Failed to allocate a buffer for stop effect.\n");
- ret = -ENOMEM;
- goto buffer_free;
+ return -ENOMEM;
}
haptic->stop_effect.input_dev = dev;
INIT_WORK(&haptic->stop_effect.work, haptic_work_handler);
@@ -507,7 +528,9 @@ int hid_haptic_init(struct hid_device *hdev,
ret = input_ff_create(dev, FF_MAX_EFFECTS);
if (ret) {
dev_err(&hdev->dev, "Failed to create ff device.\n");
- goto ff_cap_clear;
+ __clear_bit(FF_HAPTIC, dev->ffbit);
+ __clear_bit(EV_FF, dev->evbit);
+ return ret;
}
ff = dev->ff;
@@ -517,30 +540,8 @@ int hid_haptic_init(struct hid_device *hdev,
ff->stop = hid_haptic_stop;
ff->destroy = hid_haptic_destroy;
__module_get(THIS_MODULE);
- ff->private = haptic;
+ ff->private = no_free_ptr(haptic);
return 0;
-
-ff_cap_clear:
- __clear_bit(FF_HAPTIC, dev->ffbit);
- __clear_bit(EV_FF, dev->evbit);
- kfree(haptic->stop_effect.report_buf);
- haptic->stop_effect.report_buf = NULL;
-buffer_free:
- while (--r >= 0)
- kfree(haptic->effect[r].report_buf);
- kfree(haptic->effect);
- haptic->effect = NULL;
-output_queue:
- destroy_workqueue(haptic->wq);
- haptic->wq = NULL;
-duration_map:
- kfree(haptic->duration_map);
- haptic->duration_map = NULL;
-usage_map:
- kfree(haptic->hid_usage_map);
- haptic->hid_usage_map = NULL;
-exit:
- return ret;
}
EXPORT_SYMBOL_GPL(hid_haptic_init);
diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h
index 6332991..661b605 100644
--- a/drivers/hid/hid-haptic.h
+++ b/drivers/hid/hid-haptic.h
@@ -69,7 +69,8 @@ int hid_haptic_input_mapping(struct hid_device *hdev,
int hid_haptic_input_configured(struct hid_device *hdev,
struct hid_haptic_device *haptic,
struct hid_input *hi);
-int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device *haptic,
+int hid_haptic_init(struct hid_device *hdev,
+ const struct hid_haptic_device *config,
struct input_dev *dev);
void hid_haptic_handle_press_release(struct hid_haptic_device *haptic);
void hid_haptic_pressure_reset(struct hid_haptic_device *haptic);
@@ -108,7 +109,8 @@ static inline
void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic)
{}
static inline
-int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device *haptic,
+int hid_haptic_init(struct hid_device *hdev,
+ const struct hid_haptic_device *config,
struct input_dev *dev)
{
return 0;
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 154dc94..34aefe8 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -174,6 +174,7 @@ struct mt_device {
struct mt_class mtclass; /* our mt device class */
struct timer_list release_timer; /* to release sticky fingers */
struct hid_haptic_device *haptic; /* haptic related configuration */
+ struct input_dev *haptic_pressure_input;
int haptic_init_error;
struct hid_device *hdev; /* hid_device we're attached to */
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_RUNNING) */
@@ -963,9 +964,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_TIPPRESSURE:
set_abs(hi->input, ABS_MT_PRESSURE, field,
cls->sn_pressure);
- td->is_haptic_touchpad =
- hid_haptic_check_pressure_unit(td->haptic,
- hi, field);
+ if (!td->haptic_pressure_input &&
+ field->application == HID_DG_TOUCHPAD &&
+ hid_haptic_check_pressure_unit(td->haptic, hi, field)) {
+ td->haptic_pressure_input = hi->input;
+ td->is_haptic_touchpad = true;
+ }
MT_STORE_FIELD(p);
return 1;
case HID_DG_SCANTIME:
@@ -1087,7 +1091,9 @@ static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
app->num_received = 0;
app->left_button_state = 0;
- if (td->is_haptic_touchpad)
+ if (td->is_haptic_touchpad &&
+ app->application == HID_DG_TOUCHPAD &&
+ td->haptic->input_dev == input)
hid_haptic_pressure_reset(td->haptic);
}
@@ -1240,7 +1246,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
minor = minor >> 1;
}
- if (td->is_haptic_touchpad)
+ if (td->is_haptic_touchpad &&
+ app->application == HID_DG_TOUCHPAD &&
+ td->haptic->input_dev == input)
hid_haptic_pressure_increase(td->haptic, *slot->p);
x = hdev->quirks & HID_QUIRK_X_INVERT ?
@@ -1443,8 +1451,10 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (cls->is_indirect)
app->mt_flags |= INPUT_MT_POINTER;
- if (td->is_haptic_touchpad)
- app->mt_flags |= INPUT_MT_TOTAL_FORCE;
+ if (td->is_haptic_touchpad &&
+ app->application == HID_DG_TOUCHPAD &&
+ td->haptic->input_dev == input)
+ app->mt_flags |= INPUT_MT_POINTER | INPUT_MT_TOTAL_FORCE;
if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
app->mt_flags |= INPUT_MT_DROP_UNUSED;
@@ -1956,22 +1966,11 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
struct hid_report *report;
int ret;
- if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
- td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
- td->mtclass.name == MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)) {
- if (hi->application == HID_DG_TOUCHPAD) {
- ret = hid_haptic_input_configured(hdev, td->haptic, hi);
- if (ret < 0) {
- td->haptic_init_error = ret;
- td->is_haptic_touchpad = false;
- return ret;
- }
- if (ret == 0)
- td->is_haptic_touchpad = false;
- }
- } else {
+ if (td->is_haptic_touchpad &&
+ td->mtclass.name != MT_CLS_WIN_8 &&
+ td->mtclass.name != MT_CLS_WIN_8_FORCE_MULTI_INPUT &&
+ td->mtclass.name != MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE)
td->is_haptic_touchpad = false;
- }
list_for_each_entry(report, &hi->reports, hidinput_list) {
rdata = mt_find_report_data(td, report);
@@ -1983,6 +1982,22 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
mt_application = rdata->application;
if (rdata->is_mt_collection) {
+ if (td->is_haptic_touchpad &&
+ hi->application == HID_DG_TOUCHPAD &&
+ mt_application->application == HID_DG_TOUCHPAD &&
+ td->haptic_pressure_input == hi->input &&
+ !td->haptic->input_dev) {
+ ret = hid_haptic_input_configured(hdev, td->haptic,
+ hi);
+ if (ret < 0) {
+ td->haptic_init_error = ret;
+ td->is_haptic_touchpad = false;
+ return ret;
+ }
+ if (ret == 0)
+ td->is_haptic_touchpad = false;
+ }
+
ret = mt_touch_input_configured(hdev, hi,
mt_application);
if (ret)
@@ -2211,6 +2226,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
hid_hw_stop(hdev);
return ret;
}
+ if (!td->haptic->input_dev)
+ td->is_haptic_touchpad = false;
ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-17 16:41 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 16:41 [PATCH v11 0/2] HID: multitouch: fix haptic lifetime on delayed input release Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 1/2] HID: haptic: make FF creation the last fallible init step Aldo Ariel Panzardo
2026-10-17 16:41 ` [PATCH v11 2/2] HID: multitouch: give FF core ownership of haptic state Aldo Ariel Panzardo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox