Skip to content

Commit 8d0bf79

Browse files
Angela CzubakBenjamin Tissoires
authored andcommitted
HID: multitouch: add haptic multitouch support
If CONFIG_HID_HAPTIC is enabled, 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> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
1 parent ff66b8e commit 8d0bf79

2 files changed

Lines changed: 58 additions & 5 deletions

File tree

drivers/hid/hid-haptic.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,25 @@ int hid_haptic_input_configured(struct hid_device *hdev,
103103
{
104104
return 0;
105105
}
106+
static inline
107+
void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic)
108+
{}
109+
static inline
106110
int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr)
107111
{
108112
return 0;
109113
}
110114
static inline
111-
void hid_haptic_handle_press_release(struct hid_haptic_device *haptic)
112-
{}
115+
void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) {}
113116
static inline
114-
void hid_haptic_pressure_reset(struct hid_haptic_device *haptic)
115-
{}
117+
bool hid_haptic_handle_input(struct hid_haptic_device *haptic)
118+
{
119+
return false;
120+
}
121+
static inline
122+
void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) {}
116123
static inline
117124
void hid_haptic_pressure_increase(struct hid_haptic_device *haptic,
118125
__s32 pressure)
119126
{}
120127
#endif
121-

drivers/hid/hid-multitouch.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ MODULE_LICENSE("GPL");
4949

5050
#include "hid-ids.h"
5151

52+
#include "hid-haptic.h"
53+
5254
/* quirks to control the device */
5355
#define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0)
5456
#define MT_QUIRK_SLOT_IS_CONTACTID BIT(1)
@@ -168,11 +170,13 @@ struct mt_report_data {
168170
struct mt_device {
169171
struct mt_class mtclass; /* our mt device class */
170172
struct timer_list release_timer; /* to release sticky fingers */
173+
struct hid_haptic_device *haptic; /* haptic related configuration */
171174
struct hid_device *hdev; /* hid_device we're attached to */
172175
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
173176
__u8 inputmode_value; /* InputMode HID feature value */
174177
__u8 maxcontacts;
175178
bool is_buttonpad; /* is this device a button pad? */
179+
bool is_haptic_touchpad; /* is this device a haptic touchpad? */
176180
bool serial_maybe; /* need to check for serial protocol */
177181

178182
struct list_head applications;
@@ -533,6 +537,8 @@ static void mt_feature_mapping(struct hid_device *hdev,
533537
mt_get_feature(hdev, field->report);
534538
break;
535539
}
540+
541+
hid_haptic_feature_mapping(hdev, td->haptic, field, usage);
536542
}
537543

538544
static void set_abs(struct input_dev *input, unsigned int code,
@@ -888,6 +894,9 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
888894
case HID_DG_TIPPRESSURE:
889895
set_abs(hi->input, ABS_MT_PRESSURE, field,
890896
cls->sn_pressure);
897+
td->is_haptic_touchpad =
898+
hid_haptic_check_pressure_unit(td->haptic,
899+
hi, field);
891900
MT_STORE_FIELD(p);
892901
return 1;
893902
case HID_DG_SCANTIME:
@@ -1008,6 +1017,8 @@ static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
10081017

10091018
app->num_received = 0;
10101019
app->left_button_state = 0;
1020+
if (td->is_haptic_touchpad)
1021+
hid_haptic_pressure_reset(td->haptic);
10111022

10121023
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
10131024
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
@@ -1165,6 +1176,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
11651176
minor = minor >> 1;
11661177
}
11671178

1179+
if (td->is_haptic_touchpad)
1180+
hid_haptic_pressure_increase(td->haptic, *slot->p);
1181+
11681182
x = hdev->quirks & HID_QUIRK_X_INVERT ?
11691183
input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x :
11701184
*slot->x;
@@ -1366,6 +1380,9 @@ static int mt_touch_input_configured(struct hid_device *hdev,
13661380
if (cls->is_indirect)
13671381
app->mt_flags |= INPUT_MT_POINTER;
13681382

1383+
if (td->is_haptic_touchpad)
1384+
app->mt_flags |= INPUT_MT_TOTAL_FORCE;
1385+
13691386
if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
13701387
app->mt_flags |= INPUT_MT_DROP_UNUSED;
13711388

@@ -1401,6 +1418,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
14011418
struct mt_device *td = hid_get_drvdata(hdev);
14021419
struct mt_application *application;
14031420
struct mt_report_data *rdata;
1421+
int ret;
14041422

14051423
rdata = mt_find_report_data(td, field->report);
14061424
if (!rdata) {
@@ -1463,6 +1481,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
14631481
if (field->physical == HID_DG_STYLUS)
14641482
hi->application = HID_DG_STYLUS;
14651483

1484+
ret = hid_haptic_input_mapping(hdev, td->haptic, hi, field, usage, bit,
1485+
max);
1486+
if (ret != 0)
1487+
return ret;
1488+
14661489
/* let hid-core decide for the others */
14671490
return 0;
14681491
}
@@ -1685,6 +1708,14 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
16851708
struct hid_report *report;
16861709
int ret;
16871710

1711+
if (td->is_haptic_touchpad && (td->mtclass.name == MT_CLS_WIN_8 ||
1712+
td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) {
1713+
if (hid_haptic_input_configured(hdev, td->haptic, hi) == 0)
1714+
td->is_haptic_touchpad = false;
1715+
} else {
1716+
td->is_haptic_touchpad = false;
1717+
}
1718+
16881719
list_for_each_entry(report, &hi->reports, hidinput_list) {
16891720
rdata = mt_find_report_data(td, report);
16901721
if (!rdata) {
@@ -1827,6 +1858,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
18271858
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
18281859
return -ENOMEM;
18291860
}
1861+
td->haptic = devm_kzalloc(&hdev->dev, sizeof(*(td->haptic)), GFP_KERNEL);
1862+
if (!td->haptic)
1863+
return -ENOMEM;
1864+
1865+
td->haptic->hdev = hdev;
18301866
td->hdev = hdev;
18311867
td->mtclass = *mtclass;
18321868
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
@@ -1895,6 +1931,17 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
18951931

18961932
mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
18971933

1934+
if (td->is_haptic_touchpad) {
1935+
if (hid_haptic_init(hdev, &td->haptic)) {
1936+
dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n",
1937+
hdev->name);
1938+
td->is_haptic_touchpad = false;
1939+
devm_kfree(&hdev->dev, td->haptic);
1940+
}
1941+
} else {
1942+
devm_kfree(&hdev->dev, td->haptic);
1943+
}
1944+
18981945
return 0;
18991946
}
19001947

0 commit comments

Comments
 (0)