From: Jonathan Denose <jdenose@google.com>
To: Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>,
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Jonathan Corbet <corbet@lwn.net>,
Henrik Rydberg <rydberg@bitmath.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, Angela Czubak <aczubak@google.com>,
"Sean O'Brien" <seobrien@google.com>,
Jonathan Denose <jdenose@google.com>
Subject: [PATCH v2 11/11] HID: multitouch: add haptic multitouch support
Date: Mon, 18 Aug 2025 14:28:11 +0000 [thread overview]
Message-ID: <20250818-support-forcepads-v2-11-ca2546e319d5@google.com> (raw)
In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@google.com>
From: Angela Czubak <aczubak@google.com>
If CONFIG_HID_HAPTIC is configured, and the device is recognized to have
simple haptic capabilities, try initializing the haptic device, check
input frames for pressure and handle it using hid_haptic_* API.
Signed-off-by: Angela Czubak <aczubak@google.com>
Co-developed-by: Jonathan Denose <jdenose@google.com>
Signed-off-by: Jonathan Denose <jdenose@google.com>
---
drivers/hid/hid-haptic.h | 16 ++++++++++-----
drivers/hid/hid-multitouch.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h
index 73601f429de16bae3b1d877445f7eebf41a69d94..6fbe07a8df42c2dc77681b013a6f948357253bf8 100644
--- a/drivers/hid/hid-haptic.h
+++ b/drivers/hid/hid-haptic.h
@@ -107,19 +107,25 @@ int hid_haptic_input_configured(struct hid_device *hdev,
{
return 0;
}
+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_ptr)
{
return 0;
}
static inline
-void hid_haptic_handle_press_release(struct hid_haptic_device *haptic)
-{}
+void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) {}
static inline
-void hid_haptic_pressure_reset(struct hid_haptic_device *haptic)
-{}
+bool hid_haptic_handle_input(struct hid_haptic_device *haptic)
+{
+ return false;
+}
+static inline
+void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) {}
static inline
void hid_haptic_pressure_increase(struct hid_haptic_device *haptic,
__s32 pressure)
{}
#endif
-
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index b41001e02da7e02d492bd85743b359ed7ec16e7f..bbbd5c49dbd480ecad2a0c074b2f973f099dc054 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -49,6 +49,8 @@ MODULE_LICENSE("GPL");
#include "hid-ids.h"
+#include "hid-haptic.h"
+
/* quirks to control the device */
#define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0)
#define MT_QUIRK_SLOT_IS_CONTACTID BIT(1)
@@ -167,11 +169,13 @@ struct mt_report_data {
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 hid_device *hdev; /* hid_device we're attached to */
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
__u8 inputmode_value; /* InputMode HID feature value */
__u8 maxcontacts;
bool is_buttonpad; /* is this device a button pad? */
+ bool is_haptic_touchpad; /* is this device a haptic touchpad? */
bool serial_maybe; /* need to check for serial protocol */
struct list_head applications;
@@ -525,6 +529,8 @@ static void mt_feature_mapping(struct hid_device *hdev,
mt_get_feature(hdev, field->report);
break;
}
+
+ hid_haptic_feature_mapping(hdev, td->haptic, field, usage);
}
static void set_abs(struct input_dev *input, unsigned int code,
@@ -856,6 +862,9 @@ 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);
MT_STORE_FIELD(p);
return 1;
case HID_DG_SCANTIME:
@@ -980,6 +989,8 @@ 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)
+ hid_haptic_pressure_reset(td->haptic);
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
@@ -1137,6 +1148,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
minor = minor >> 1;
}
+ if (td->is_haptic_touchpad)
+ hid_haptic_pressure_increase(td->haptic, *slot->p);
+
x = hdev->quirks & HID_QUIRK_X_INVERT ?
input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x :
*slot->x;
@@ -1324,6 +1338,9 @@ 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 (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
app->mt_flags |= INPUT_MT_DROP_UNUSED;
@@ -1359,6 +1376,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_application *application;
struct mt_report_data *rdata;
+ int ret;
rdata = mt_find_report_data(td, field->report);
if (!rdata) {
@@ -1421,6 +1439,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->physical == HID_DG_STYLUS)
hi->application = HID_DG_STYLUS;
+ ret = hid_haptic_input_mapping(hdev, td->haptic, hi, field, usage, bit,
+ max);
+ if (ret != 0)
+ return ret;
+
/* let hid-core decide for the others */
return 0;
}
@@ -1635,6 +1658,14 @@ 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)) {
+ if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
+ td->is_haptic_touchpad = false;
+ } else {
+ td->is_haptic_touchpad = false;
+ }
+
list_for_each_entry(report, &hi->reports, hidinput_list) {
rdata = mt_find_report_data(td, report);
if (!rdata) {
@@ -1777,6 +1808,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
return -ENOMEM;
}
+ td->haptic = devm_kzalloc(&td->hdev->dev, sizeof(*(td->haptic)), GFP_KERNEL);
+ if (!td->haptic)
+ return -ENOMEM;
+
+ td->haptic->hdev = hdev;
td->hdev = hdev;
td->mtclass = *mtclass;
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
@@ -1840,6 +1876,17 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
+ if (td->is_haptic_touchpad) {
+ if (hid_haptic_init(hdev, &td->haptic)) {
+ dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n",
+ hdev->name);
+ td->is_haptic_touchpad = false;
+ devm_kfree(&td->hdev->dev, td->haptic);
+ }
+ } else {
+ devm_kfree(&td->hdev->dev, td->haptic);
+ }
+
return 0;
}
--
2.51.0.rc1.163.g2494970778-goog
next prev parent reply other threads:[~2025-08-18 14:29 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-18 14:28 [PATCH v2 00/11] HID: Implement haptic touchpad support Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 01/11] HID: add haptics page defines Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 02/11] Input: add FF_HAPTIC effect type Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 03/11] Input: add INPUT_PROP_HAPTIC_TOUCHPAD Jonathan Denose
2025-08-18 16:31 ` Randy Dunlap
2025-08-18 14:28 ` [PATCH v2 04/11] HID: haptic: introduce hid_haptic_device Jonathan Denose
2025-08-18 16:36 ` Randy Dunlap
2025-08-18 22:17 ` Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 05/11] HID: input: allow mapping of haptic output Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 06/11] HID: haptic: initialize haptic device Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 07/11] HID: input: calculate resolution for pressure Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 08/11] HID: haptic: add functions handling events Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 09/11] Input: MT - add INPUT_MT_TOTAL_FORCE flags Jonathan Denose
2025-08-18 14:28 ` [PATCH v2 10/11] HID: haptic: add hid_haptic_switch_mode Jonathan Denose
2025-08-18 14:28 ` Jonathan Denose [this message]
2025-08-18 14:34 ` [PATCH v2 00/11] HID: Implement haptic touchpad support Jonathan Denose
-- strict thread matches above, loose matches on Subject: below --
2025-08-04 14:11 Jonathan Denose
2025-08-04 14:11 ` [PATCH v2 11/11] HID: multitouch: add haptic multitouch support Jonathan Denose
2025-08-13 9:22 ` Benjamin Tissoires
2025-08-13 15:52 ` Jonathan Denose
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250818-support-forcepads-v2-11-ca2546e319d5@google.com \
--to=jdenose@google.com \
--cc=aczubak@google.com \
--cc=bentiss@kernel.org \
--cc=corbet@lwn.net \
--cc=dmitry.torokhov@gmail.com \
--cc=jikos@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rydberg@bitmath.org \
--cc=seobrien@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).