Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: hid-plantronics: Add mic mute mapping and generalize quirks

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 <linuxhid@cosmicgizmosystems.com>
Cc: stable@vger.kernel.org
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Terry Junge and committed by
Jiri Kosina
9821709a 27c02784

+67 -77
+67 -77
drivers/hid/hid-plantronics.c
··· 6 6 * Copyright (c) 2015-2018 Terry Junge <terry.junge@plantronics.com> 7 7 */ 8 8 9 - /* 10 - */ 11 - 12 9 #include "hid-ids.h" 13 10 14 11 #include <linux/hid.h> ··· 20 23 21 24 #define PLT_VOL_UP 0x00b1 22 25 #define PLT_VOL_DOWN 0x00b2 26 + #define PLT_MIC_MUTE 0x00b5 23 27 24 28 #define PLT1_VOL_UP (PLT_HID_1_0_PAGE | PLT_VOL_UP) 25 29 #define PLT1_VOL_DOWN (PLT_HID_1_0_PAGE | PLT_VOL_DOWN) 30 + #define PLT1_MIC_MUTE (PLT_HID_1_0_PAGE | PLT_MIC_MUTE) 26 31 #define PLT2_VOL_UP (PLT_HID_2_0_PAGE | PLT_VOL_UP) 27 32 #define PLT2_VOL_DOWN (PLT_HID_2_0_PAGE | PLT_VOL_DOWN) 33 + #define PLT2_MIC_MUTE (PLT_HID_2_0_PAGE | PLT_MIC_MUTE) 34 + #define HID_TELEPHONY_MUTE (HID_UP_TELEPHONY | 0x2f) 35 + #define HID_CONSUMER_MUTE (HID_UP_CONSUMER | 0xe2) 28 36 29 37 #define PLT_DA60 0xda60 30 38 #define PLT_BT300_MIN 0x0413 31 39 #define PLT_BT300_MAX 0x0418 32 40 33 - 34 - #define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \ 35 - (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) 36 - 37 - #define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0) 38 - #define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1) 39 - 40 41 #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */ 41 - #define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */ 42 42 43 43 struct plt_drv_data { 44 44 unsigned long device_type; 45 - unsigned long last_volume_key_ts; 46 - u32 quirks; 45 + unsigned long last_key_ts; 46 + unsigned long double_key_to; 47 + __u16 last_key; 47 48 }; 48 49 49 50 static int plantronics_input_mapping(struct hid_device *hdev, ··· 53 58 unsigned short mapped_key; 54 59 struct plt_drv_data *drv_data = hid_get_drvdata(hdev); 55 60 unsigned long plt_type = drv_data->device_type; 61 + int allow_mute = usage->hid == HID_TELEPHONY_MUTE; 62 + int allow_consumer = field->application == HID_CP_CONSUMERCONTROL && 63 + (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER && 64 + usage->hid != HID_CONSUMER_MUTE; 56 65 57 66 /* special case for PTT products */ 58 67 if (field->application == HID_GD_JOYSTICK) 59 68 goto defaulted; 60 69 61 - /* handle volume up/down mapping */ 62 70 /* non-standard types or multi-HID interfaces - plt_type is PID */ 63 71 if (!(plt_type & HID_USAGE_PAGE)) { 64 72 switch (plt_type) { 65 73 case PLT_DA60: 66 - if (PLT_ALLOW_CONSUMER) 74 + if (allow_consumer) 67 75 goto defaulted; 68 - goto ignored; 76 + if (usage->hid == HID_CONSUMER_MUTE) { 77 + mapped_key = KEY_MICMUTE; 78 + goto mapped; 79 + } 80 + break; 69 81 default: 70 - if (PLT_ALLOW_CONSUMER) 82 + if (allow_consumer || allow_mute) 71 83 goto defaulted; 72 84 } 85 + goto ignored; 73 86 } 74 - /* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */ 75 - /* 'basic telephony compliant' - allow default consumer page map */ 76 - else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY && 77 - (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) { 78 - if (PLT_ALLOW_CONSUMER) 79 - goto defaulted; 80 - } 81 - /* not 'basic telephony' - apply legacy mapping */ 82 - /* only map if the field is in the device's primary vendor page */ 83 - else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) { 87 + 88 + /* handle standard consumer control mapping */ 89 + /* and standard telephony mic mute mapping */ 90 + if (allow_consumer || allow_mute) 91 + goto defaulted; 92 + 93 + /* handle vendor unique types - plt_type is 0xffa0uuuu or 0xffa2uuuu */ 94 + /* if not 'basic telephony compliant' - map vendor unique controls */ 95 + if (!((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY && 96 + (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) && 97 + !((field->application ^ plt_type) & HID_USAGE_PAGE)) 84 98 switch (usage->hid) { 85 99 case PLT1_VOL_UP: 86 100 case PLT2_VOL_UP: ··· 99 95 case PLT2_VOL_DOWN: 100 96 mapped_key = KEY_VOLUMEDOWN; 101 97 goto mapped; 98 + case PLT1_MIC_MUTE: 99 + case PLT2_MIC_MUTE: 100 + mapped_key = KEY_MICMUTE; 101 + goto mapped; 102 102 } 103 - } 104 103 105 104 /* 106 105 * Future mapping of call control or other usages, ··· 112 105 */ 113 106 114 107 ignored: 108 + hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n", 109 + usage->hid, field->application); 115 110 return -1; 116 111 117 112 defaulted: ··· 132 123 struct hid_usage *usage, __s32 value) 133 124 { 134 125 struct plt_drv_data *drv_data = hid_get_drvdata(hdev); 126 + unsigned long prev_tsto, cur_ts; 127 + __u16 prev_key, cur_key; 135 128 136 - if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) { 137 - unsigned long prev_ts, cur_ts; 129 + /* Usages are filtered in plantronics_usages. */ 138 130 139 - /* Usages are filtered in plantronics_usages. */ 131 + /* HZ too low for ms resolution - double key detection disabled */ 132 + /* or it is a key release - handle key presses only. */ 133 + if (!drv_data->double_key_to || !value) 134 + return 0; 140 135 141 - if (!value) /* Handle key presses only. */ 142 - return 0; 136 + prev_tsto = drv_data->last_key_ts + drv_data->double_key_to; 137 + cur_ts = drv_data->last_key_ts = jiffies; 138 + prev_key = drv_data->last_key; 139 + cur_key = drv_data->last_key = usage->code; 143 140 144 - prev_ts = drv_data->last_volume_key_ts; 145 - cur_ts = jiffies; 146 - if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_DOUBLE_KEY_TIMEOUT) 147 - return 1; /* Ignore the repeated key. */ 148 - 149 - drv_data->last_volume_key_ts = cur_ts; 141 + /* If the same key occurs in <= double_key_to -- ignore it */ 142 + if (prev_key == cur_key && time_before_eq(cur_ts, prev_tsto)) { 143 + hid_dbg(hdev, "double key %d ignored\n", cur_key); 144 + return 1; /* Ignore the repeated key. */ 150 145 } 151 - if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) { 152 - unsigned long prev_ts, cur_ts; 153 - 154 - /* Usages are filtered in plantronics_usages. */ 155 - 156 - if (!value) /* Handle key presses only. */ 157 - return 0; 158 - 159 - prev_ts = drv_data->last_volume_key_ts; 160 - cur_ts = jiffies; 161 - if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT) 162 - return 1; /* Ignore the followed opposite volume key. */ 163 - 164 - drv_data->last_volume_key_ts = cur_ts; 165 - } 166 - 167 146 return 0; 168 147 } 169 148 ··· 193 196 ret = hid_parse(hdev); 194 197 if (ret) { 195 198 hid_err(hdev, "parse failed\n"); 196 - goto err; 199 + return ret; 197 200 } 198 201 199 202 drv_data->device_type = plantronics_device_type(hdev); 200 - drv_data->quirks = id->driver_data; 201 - drv_data->last_volume_key_ts = jiffies - msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT); 203 + drv_data->double_key_to = msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT); 204 + drv_data->last_key_ts = jiffies - drv_data->double_key_to; 205 + 206 + /* if HZ does not allow ms resolution - disable double key detection */ 207 + if (drv_data->double_key_to < PLT_DOUBLE_KEY_TIMEOUT) 208 + drv_data->double_key_to = 0; 202 209 203 210 hid_set_drvdata(hdev, drv_data); 204 211 ··· 211 210 if (ret) 212 211 hid_err(hdev, "hw start failed\n"); 213 212 214 - err: 215 213 return ret; 216 214 } 217 215 218 216 static const struct hid_device_id plantronics_devices[] = { 219 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 220 - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES), 221 - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, 222 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 223 - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES), 224 - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, 225 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 226 - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES), 227 - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, 228 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 229 - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES), 230 - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, 231 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 232 - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES), 233 - .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, 234 - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, 235 - USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES), 236 - .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, 237 217 { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, 238 218 { } 239 219 }; ··· 223 241 static const struct hid_usage_id plantronics_usages[] = { 224 242 { HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID }, 225 243 { HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID }, 244 + { HID_TELEPHONY_MUTE, EV_KEY, HID_ANY_ID }, 245 + { HID_CONSUMER_MUTE, EV_KEY, HID_ANY_ID }, 246 + { PLT2_VOL_UP, EV_KEY, HID_ANY_ID }, 247 + { PLT2_VOL_DOWN, EV_KEY, HID_ANY_ID }, 248 + { PLT2_MIC_MUTE, EV_KEY, HID_ANY_ID }, 249 + { PLT1_VOL_UP, EV_KEY, HID_ANY_ID }, 250 + { PLT1_VOL_DOWN, EV_KEY, HID_ANY_ID }, 251 + { PLT1_MIC_MUTE, EV_KEY, HID_ANY_ID }, 226 252 { HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR } 227 253 }; 228 254