Skip to content

Commit dddd13f

Browse files
Terry Jungegregkh
Terry Junge
authored andcommitted
HID: hid-plantronics: Add mic mute mapping and generalize quirks
commit 9821709 upstream. Add mapping for headset mute key events. Remove PLT_QUIRK_DOUBLE_VOLUME_KEYS quirk and made it generic. The quirk logic did not keep track of the actual previous key so any key event occurring in less than or equal to 5ms was ignored. Remove PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS quirk. It had the same logic issue as the double key quirk and was actually masking the as designed behavior of most of the headsets. It's occurrence should be minimized with the ALSA control naming quirk that is part of the patch set. Signed-off-by: Terry Junge <[email protected]> Cc: [email protected] Signed-off-by: Jiri Kosina <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a532e76 commit dddd13f

File tree

1 file changed

+67
-77
lines changed

1 file changed

+67
-77
lines changed

drivers/hid/hid-plantronics.c

Lines changed: 67 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
* Copyright (c) 2015-2018 Terry Junge <[email protected]>
77
*/
88

9-
/*
10-
*/
11-
129
#include "hid-ids.h"
1310

1411
#include <linux/hid.h>
@@ -23,30 +20,28 @@
2320

2421
#define PLT_VOL_UP 0x00b1
2522
#define PLT_VOL_DOWN 0x00b2
23+
#define PLT_MIC_MUTE 0x00b5
2624

2725
#define PLT1_VOL_UP (PLT_HID_1_0_PAGE | PLT_VOL_UP)
2826
#define PLT1_VOL_DOWN (PLT_HID_1_0_PAGE | PLT_VOL_DOWN)
27+
#define PLT1_MIC_MUTE (PLT_HID_1_0_PAGE | PLT_MIC_MUTE)
2928
#define PLT2_VOL_UP (PLT_HID_2_0_PAGE | PLT_VOL_UP)
3029
#define PLT2_VOL_DOWN (PLT_HID_2_0_PAGE | PLT_VOL_DOWN)
30+
#define PLT2_MIC_MUTE (PLT_HID_2_0_PAGE | PLT_MIC_MUTE)
31+
#define HID_TELEPHONY_MUTE (HID_UP_TELEPHONY | 0x2f)
32+
#define HID_CONSUMER_MUTE (HID_UP_CONSUMER | 0xe2)
3133

3234
#define PLT_DA60 0xda60
3335
#define PLT_BT300_MIN 0x0413
3436
#define PLT_BT300_MAX 0x0418
3537

36-
37-
#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \
38-
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
39-
40-
#define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0)
41-
#define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1)
42-
4338
#define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */
44-
#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */
4539

4640
struct plt_drv_data {
4741
unsigned long device_type;
48-
unsigned long last_volume_key_ts;
49-
u32 quirks;
42+
unsigned long last_key_ts;
43+
unsigned long double_key_to;
44+
__u16 last_key;
5045
};
5146

5247
static int plantronics_input_mapping(struct hid_device *hdev,
@@ -58,34 +53,43 @@ static int plantronics_input_mapping(struct hid_device *hdev,
5853
unsigned short mapped_key;
5954
struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
6055
unsigned long plt_type = drv_data->device_type;
56+
int allow_mute = usage->hid == HID_TELEPHONY_MUTE;
57+
int allow_consumer = field->application == HID_CP_CONSUMERCONTROL &&
58+
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
59+
usage->hid != HID_CONSUMER_MUTE;
6160

6261
/* special case for PTT products */
6362
if (field->application == HID_GD_JOYSTICK)
6463
goto defaulted;
6564

66-
/* handle volume up/down mapping */
6765
/* non-standard types or multi-HID interfaces - plt_type is PID */
6866
if (!(plt_type & HID_USAGE_PAGE)) {
6967
switch (plt_type) {
7068
case PLT_DA60:
71-
if (PLT_ALLOW_CONSUMER)
69+
if (allow_consumer)
7270
goto defaulted;
73-
goto ignored;
71+
if (usage->hid == HID_CONSUMER_MUTE) {
72+
mapped_key = KEY_MICMUTE;
73+
goto mapped;
74+
}
75+
break;
7476
default:
75-
if (PLT_ALLOW_CONSUMER)
77+
if (allow_consumer || allow_mute)
7678
goto defaulted;
7779
}
80+
goto ignored;
7881
}
79-
/* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
80-
/* 'basic telephony compliant' - allow default consumer page map */
81-
else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
82-
(plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) {
83-
if (PLT_ALLOW_CONSUMER)
84-
goto defaulted;
85-
}
86-
/* not 'basic telephony' - apply legacy mapping */
87-
/* only map if the field is in the device's primary vendor page */
88-
else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) {
82+
83+
/* handle standard consumer control mapping */
84+
/* and standard telephony mic mute mapping */
85+
if (allow_consumer || allow_mute)
86+
goto defaulted;
87+
88+
/* handle vendor unique types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
89+
/* if not 'basic telephony compliant' - map vendor unique controls */
90+
if (!((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
91+
(plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) &&
92+
!((field->application ^ plt_type) & HID_USAGE_PAGE))
8993
switch (usage->hid) {
9094
case PLT1_VOL_UP:
9195
case PLT2_VOL_UP:
@@ -95,8 +99,11 @@ static int plantronics_input_mapping(struct hid_device *hdev,
9599
case PLT2_VOL_DOWN:
96100
mapped_key = KEY_VOLUMEDOWN;
97101
goto mapped;
102+
case PLT1_MIC_MUTE:
103+
case PLT2_MIC_MUTE:
104+
mapped_key = KEY_MICMUTE;
105+
goto mapped;
98106
}
99-
}
100107

101108
/*
102109
* Future mapping of call control or other usages,
@@ -105,6 +112,8 @@ static int plantronics_input_mapping(struct hid_device *hdev,
105112
*/
106113

107114
ignored:
115+
hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n",
116+
usage->hid, field->application);
108117
return -1;
109118

110119
defaulted:
@@ -123,38 +132,26 @@ static int plantronics_event(struct hid_device *hdev, struct hid_field *field,
123132
struct hid_usage *usage, __s32 value)
124133
{
125134
struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
135+
unsigned long prev_tsto, cur_ts;
136+
__u16 prev_key, cur_key;
126137

127-
if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) {
128-
unsigned long prev_ts, cur_ts;
138+
/* Usages are filtered in plantronics_usages. */
129139

130-
/* Usages are filtered in plantronics_usages. */
140+
/* HZ too low for ms resolution - double key detection disabled */
141+
/* or it is a key release - handle key presses only. */
142+
if (!drv_data->double_key_to || !value)
143+
return 0;
131144

132-
if (!value) /* Handle key presses only. */
133-
return 0;
145+
prev_tsto = drv_data->last_key_ts + drv_data->double_key_to;
146+
cur_ts = drv_data->last_key_ts = jiffies;
147+
prev_key = drv_data->last_key;
148+
cur_key = drv_data->last_key = usage->code;
134149

135-
prev_ts = drv_data->last_volume_key_ts;
136-
cur_ts = jiffies;
137-
if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_DOUBLE_KEY_TIMEOUT)
138-
return 1; /* Ignore the repeated key. */
139-
140-
drv_data->last_volume_key_ts = cur_ts;
150+
/* If the same key occurs in <= double_key_to -- ignore it */
151+
if (prev_key == cur_key && time_before_eq(cur_ts, prev_tsto)) {
152+
hid_dbg(hdev, "double key %d ignored\n", cur_key);
153+
return 1; /* Ignore the repeated key. */
141154
}
142-
if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) {
143-
unsigned long prev_ts, cur_ts;
144-
145-
/* Usages are filtered in plantronics_usages. */
146-
147-
if (!value) /* Handle key presses only. */
148-
return 0;
149-
150-
prev_ts = drv_data->last_volume_key_ts;
151-
cur_ts = jiffies;
152-
if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT)
153-
return 1; /* Ignore the followed opposite volume key. */
154-
155-
drv_data->last_volume_key_ts = cur_ts;
156-
}
157-
158155
return 0;
159156
}
160157

@@ -196,12 +193,16 @@ static int plantronics_probe(struct hid_device *hdev,
196193
ret = hid_parse(hdev);
197194
if (ret) {
198195
hid_err(hdev, "parse failed\n");
199-
goto err;
196+
return ret;
200197
}
201198

202199
drv_data->device_type = plantronics_device_type(hdev);
203-
drv_data->quirks = id->driver_data;
204-
drv_data->last_volume_key_ts = jiffies - msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT);
200+
drv_data->double_key_to = msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT);
201+
drv_data->last_key_ts = jiffies - drv_data->double_key_to;
202+
203+
/* if HZ does not allow ms resolution - disable double key detection */
204+
if (drv_data->double_key_to < PLT_DOUBLE_KEY_TIMEOUT)
205+
drv_data->double_key_to = 0;
205206

206207
hid_set_drvdata(hdev, drv_data);
207208

@@ -210,29 +211,10 @@ static int plantronics_probe(struct hid_device *hdev,
210211
if (ret)
211212
hid_err(hdev, "hw start failed\n");
212213

213-
err:
214214
return ret;
215215
}
216216

217217
static const struct hid_device_id plantronics_devices[] = {
218-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
219-
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES),
220-
.driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
221-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
222-
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES),
223-
.driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
224-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
225-
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES),
226-
.driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
227-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
228-
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES),
229-
.driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
230-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
231-
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES),
232-
.driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
233-
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
234-
USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES),
235-
.driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
236218
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
237219
{ }
238220
};
@@ -241,6 +223,14 @@ MODULE_DEVICE_TABLE(hid, plantronics_devices);
241223
static const struct hid_usage_id plantronics_usages[] = {
242224
{ HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID },
243225
{ HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID },
226+
{ HID_TELEPHONY_MUTE, EV_KEY, HID_ANY_ID },
227+
{ HID_CONSUMER_MUTE, EV_KEY, HID_ANY_ID },
228+
{ PLT2_VOL_UP, EV_KEY, HID_ANY_ID },
229+
{ PLT2_VOL_DOWN, EV_KEY, HID_ANY_ID },
230+
{ PLT2_MIC_MUTE, EV_KEY, HID_ANY_ID },
231+
{ PLT1_VOL_UP, EV_KEY, HID_ANY_ID },
232+
{ PLT1_VOL_DOWN, EV_KEY, HID_ANY_ID },
233+
{ PLT1_MIC_MUTE, EV_KEY, HID_ANY_ID },
244234
{ HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR }
245235
};
246236

0 commit comments

Comments
 (0)