Skip to content

Commit b44779d

Browse files
Angela CzubakBenjamin Tissoires
authored andcommitted
HID: haptic: introduce hid_haptic_device
Define a new structure that contains simple haptic device configuration as well as current state. Add functions that recognize auto trigger and manual trigger reports as well as save their addresses. Verify that the pressure unit is either grams or newtons. Mark the input device as a haptic touchpad if the unit is correct and the reports are found. 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 7075ae4 commit b44779d

4 files changed

Lines changed: 185 additions & 0 deletions

File tree

drivers/hid/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ config HID_GENERIC
9292

9393
If unsure, say Y.
9494

95+
config HID_HAPTIC
96+
tristate "Haptic touchpad support"
97+
default n
98+
help
99+
Support for touchpads with force sensors and haptic actuators instead of a
100+
traditional button.
101+
Adds extra parsing and FF device for the hid multitouch driver.
102+
It can be used for Elan 2703 haptic touchpad.
103+
104+
If unsure, say N.
105+
95106
menu "Special HID drivers"
96107

97108
config HID_A4TECH

drivers/hid/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#
55
hid-y := hid-core.o hid-input.o hid-quirks.o
66
hid-$(CONFIG_DEBUG_FS) += hid-debug.o
7+
hid-$(CONFIG_HID_HAPTIC) += hid-haptic.o
78

89
obj-$(CONFIG_HID_BPF) += bpf/
910

drivers/hid/hid-haptic.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* HID Haptic support for Linux
4+
*
5+
* Copyright (c) 2021 Angela Czubak <acz@semihalf.com>
6+
*/
7+
8+
#include "hid-haptic.h"
9+
10+
void hid_haptic_feature_mapping(struct hid_device *hdev,
11+
struct hid_haptic_device *haptic,
12+
struct hid_field *field, struct hid_usage *usage)
13+
{
14+
if (usage->hid == HID_HP_AUTOTRIGGER) {
15+
if (usage->usage_index >= field->report_count) {
16+
dev_err(&hdev->dev,
17+
"HID_HP_AUTOTRIGGER out of range\n");
18+
return;
19+
}
20+
21+
hid_device_io_start(hdev);
22+
hid_hw_request(hdev, field->report, HID_REQ_GET_REPORT);
23+
hid_hw_wait(hdev);
24+
hid_device_io_stop(hdev);
25+
haptic->default_auto_trigger =
26+
field->value[usage->usage_index];
27+
haptic->auto_trigger_report = field->report;
28+
}
29+
}
30+
EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping);
31+
32+
bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic,
33+
struct hid_input *hi, struct hid_field *field)
34+
{
35+
if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON)
36+
return true;
37+
return false;
38+
}
39+
EXPORT_SYMBOL_GPL(hid_haptic_check_pressure_unit);
40+
41+
int hid_haptic_input_mapping(struct hid_device *hdev,
42+
struct hid_haptic_device *haptic,
43+
struct hid_input *hi,
44+
struct hid_field *field, struct hid_usage *usage,
45+
unsigned long **bit, int *max)
46+
{
47+
if (usage->hid == HID_HP_MANUALTRIGGER) {
48+
haptic->manual_trigger_report = field->report;
49+
/* we don't really want to map these fields */
50+
return -1;
51+
}
52+
53+
return 0;
54+
}
55+
EXPORT_SYMBOL_GPL(hid_haptic_input_mapping);
56+
57+
int hid_haptic_input_configured(struct hid_device *hdev,
58+
struct hid_haptic_device *haptic,
59+
struct hid_input *hi)
60+
{
61+
62+
if (hi->application == HID_DG_TOUCHPAD) {
63+
if (haptic->auto_trigger_report &&
64+
haptic->manual_trigger_report) {
65+
__set_bit(INPUT_PROP_HAPTIC_TOUCHPAD, hi->input->propbit);
66+
return 1;
67+
}
68+
return 0;
69+
}
70+
return -1;
71+
}
72+
EXPORT_SYMBOL_GPL(hid_haptic_input_configured);

drivers/hid/hid-haptic.h

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* HID Haptic support for Linux
4+
*
5+
* Copyright (c) 2021 Angela Czubak <acz@semihalf.com>
6+
*/
7+
8+
#include <linux/hid.h>
9+
10+
#define HID_HAPTIC_ORDINAL_WAVEFORMNONE 1
11+
#define HID_HAPTIC_ORDINAL_WAVEFORMSTOP 2
12+
13+
#define HID_HAPTIC_MODE_DEVICE 0
14+
#define HID_HAPTIC_MODE_HOST 1
15+
16+
struct hid_haptic_effect {
17+
u8 *report_buf;
18+
struct input_dev *input_dev;
19+
struct work_struct work;
20+
struct list_head control;
21+
struct mutex control_mutex;
22+
};
23+
24+
struct hid_haptic_effect_node {
25+
struct list_head node;
26+
struct file *file;
27+
};
28+
29+
struct hid_haptic_device {
30+
struct input_dev *input_dev;
31+
struct hid_device *hdev;
32+
struct hid_report *auto_trigger_report;
33+
struct mutex auto_trigger_mutex;
34+
struct workqueue_struct *wq;
35+
struct hid_report *manual_trigger_report;
36+
struct mutex manual_trigger_mutex;
37+
size_t manual_trigger_report_len;
38+
int pressed_state;
39+
s32 pressure_sum;
40+
s32 force_logical_minimum;
41+
s32 force_physical_minimum;
42+
s32 force_resolution;
43+
u32 mode;
44+
u32 default_auto_trigger;
45+
u32 vendor_page;
46+
u32 vendor_id;
47+
u32 max_waveform_id;
48+
u32 max_duration_id;
49+
u16 *hid_usage_map;
50+
u32 *duration_map;
51+
u16 press_ordinal;
52+
u16 release_ordinal;
53+
struct hid_haptic_effect *effect;
54+
struct hid_haptic_effect stop_effect;
55+
};
56+
57+
#if IS_ENABLED(CONFIG_HID_HAPTIC)
58+
void hid_haptic_feature_mapping(struct hid_device *hdev,
59+
struct hid_haptic_device *haptic,
60+
struct hid_field *field, struct hid_usage
61+
*usage);
62+
bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic,
63+
struct hid_input *hi, struct hid_field *field);
64+
int hid_haptic_input_mapping(struct hid_device *hdev,
65+
struct hid_haptic_device *haptic,
66+
struct hid_input *hi,
67+
struct hid_field *field, struct hid_usage *usage,
68+
unsigned long **bit, int *max);
69+
int hid_haptic_input_configured(struct hid_device *hdev,
70+
struct hid_haptic_device *haptic,
71+
struct hid_input *hi);
72+
#else
73+
static inline
74+
void hid_haptic_feature_mapping(struct hid_device *hdev,
75+
struct hid_haptic_device *haptic,
76+
struct hid_field *field, struct hid_usage
77+
*usage)
78+
{}
79+
static inline
80+
bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic,
81+
struct hid_input *hi, struct hid_field *field)
82+
{
83+
return false;
84+
}
85+
static inline
86+
int hid_haptic_input_mapping(struct hid_device *hdev,
87+
struct hid_haptic_device *haptic,
88+
struct hid_input *hi,
89+
struct hid_field *field, struct hid_usage *usage,
90+
unsigned long **bit, int *max)
91+
{
92+
return 0;
93+
}
94+
static inline
95+
int hid_haptic_input_configured(struct hid_device *hdev,
96+
struct hid_haptic_device *haptic,
97+
struct hid_input *hi)
98+
{
99+
return 0;
100+
}
101+
#endif

0 commit comments

Comments
 (0)