Skip to content

Commit 74ed6b5

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.15/plantronics' into for-linus
- improved mute handling (Terry Junge)
2 parents 765b8aa + 486f620 commit 74ed6b5

File tree

2 files changed

+118
-77
lines changed

2 files changed

+118
-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 <terry.junge@plantronics.com>
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

sound/usb/mixer_quirks.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4223,6 +4223,52 @@ static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
42234223
}
42244224
}
42254225

4226+
/*
4227+
* Some Plantronics headsets have control names that don't meet ALSA naming
4228+
* standards. This function fixes nonstandard source names. By the time
4229+
* this function is called the control name should look like one of these:
4230+
* "source names Playback Volume"
4231+
* "source names Playback Switch"
4232+
* "source names Capture Volume"
4233+
* "source names Capture Switch"
4234+
* If any of the trigger words are found in the name then the name will
4235+
* be changed to:
4236+
* "Headset Playback Volume"
4237+
* "Headset Playback Switch"
4238+
* "Headset Capture Volume"
4239+
* "Headset Capture Switch"
4240+
* depending on the current suffix.
4241+
*/
4242+
static void snd_fix_plt_name(struct snd_usb_audio *chip,
4243+
struct snd_ctl_elem_id *id)
4244+
{
4245+
/* no variant of "Sidetone" should be added to this list */
4246+
static const char * const trigger[] = {
4247+
"Earphone", "Microphone", "Receive", "Transmit"
4248+
};
4249+
static const char * const suffix[] = {
4250+
" Playback Volume", " Playback Switch",
4251+
" Capture Volume", " Capture Switch"
4252+
};
4253+
int i;
4254+
4255+
for (i = 0; i < ARRAY_SIZE(trigger); i++)
4256+
if (strstr(id->name, trigger[i]))
4257+
goto triggered;
4258+
usb_audio_dbg(chip, "no change in %s\n", id->name);
4259+
return;
4260+
4261+
triggered:
4262+
for (i = 0; i < ARRAY_SIZE(suffix); i++)
4263+
if (strstr(id->name, suffix[i])) {
4264+
usb_audio_dbg(chip, "fixing kctl name %s\n", id->name);
4265+
snprintf(id->name, sizeof(id->name), "Headset%s",
4266+
suffix[i]);
4267+
return;
4268+
}
4269+
usb_audio_dbg(chip, "something wrong in kctl name %s\n", id->name);
4270+
}
4271+
42264272
void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
42274273
struct usb_mixer_elem_info *cval, int unitid,
42284274
struct snd_kcontrol *kctl)
@@ -4240,5 +4286,10 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
42404286
cval->min_mute = 1;
42414287
break;
42424288
}
4289+
4290+
/* ALSA-ify some Plantronics headset control names */
4291+
if (USB_ID_VENDOR(mixer->chip->usb_id) == 0x047f &&
4292+
(cval->control == UAC_FU_MUTE || cval->control == UAC_FU_VOLUME))
4293+
snd_fix_plt_name(mixer->chip, &kctl->id);
42434294
}
42444295

0 commit comments

Comments
 (0)