Also, FYI base-commit: bcde95ce32b666478d6737219caa4f8005a8f201 for the series... Thanks, On 12/23/24 10:56 PM, Wade Wang wrote: > From: Terry Junge <linuxhid@xxxxxxxxxxxxxxxxxxxxxx> > > 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@xxxxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Wade Wang <wade.wang@xxxxxx> > Cc: stable@xxxxxxxxxxxxxxx > --- > V1 -> V2: Optimize out 2 macros - no functional changes > > drivers/hid/hid-plantronics.c | 144 ++++++++++++++++------------------ > 1 file changed, 67 insertions(+), 77 deletions(-) > > diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c > index 25cfd964dc25..acb9eb18f7cc 100644 > --- a/drivers/hid/hid-plantronics.c > +++ b/drivers/hid/hid-plantronics.c > @@ -6,9 +6,6 @@ > * Copyright (c) 2015-2018 Terry Junge <terry.junge@xxxxxxxxxxxxxxx> > */ > > -/* > - */ > - > #include "hid-ids.h" > > #include <linux/hid.h> > @@ -23,30 +20,28 @@ > > #define PLT_VOL_UP 0x00b1 > #define PLT_VOL_DOWN 0x00b2 > +#define PLT_MIC_MUTE 0x00b5 > > #define PLT1_VOL_UP (PLT_HID_1_0_PAGE | PLT_VOL_UP) > #define PLT1_VOL_DOWN (PLT_HID_1_0_PAGE | PLT_VOL_DOWN) > +#define PLT1_MIC_MUTE (PLT_HID_1_0_PAGE | PLT_MIC_MUTE) > #define PLT2_VOL_UP (PLT_HID_2_0_PAGE | PLT_VOL_UP) > #define PLT2_VOL_DOWN (PLT_HID_2_0_PAGE | PLT_VOL_DOWN) > +#define PLT2_MIC_MUTE (PLT_HID_2_0_PAGE | PLT_MIC_MUTE) > +#define HID_TELEPHONY_MUTE (HID_UP_TELEPHONY | 0x2f) > +#define HID_CONSUMER_MUTE (HID_UP_CONSUMER | 0xe2) > > #define PLT_DA60 0xda60 > #define PLT_BT300_MIN 0x0413 > #define PLT_BT300_MAX 0x0418 > > - > -#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \ > - (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) > - > -#define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0) > -#define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1) > - > #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */ > -#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */ > > struct plt_drv_data { > unsigned long device_type; > - unsigned long last_volume_key_ts; > - u32 quirks; > + unsigned long last_key_ts; > + unsigned long double_key_to; > + __u16 last_key; > }; > > static int plantronics_input_mapping(struct hid_device *hdev, > @@ -58,34 +53,43 @@ static int plantronics_input_mapping(struct hid_device *hdev, > unsigned short mapped_key; > struct plt_drv_data *drv_data = hid_get_drvdata(hdev); > unsigned long plt_type = drv_data->device_type; > + int allow_mute = usage->hid == HID_TELEPHONY_MUTE; > + int allow_consumer = field->application == HID_CP_CONSUMERCONTROL && > + (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER && > + usage->hid != HID_CONSUMER_MUTE; > > /* special case for PTT products */ > if (field->application == HID_GD_JOYSTICK) > goto defaulted; > > - /* handle volume up/down mapping */ > /* non-standard types or multi-HID interfaces - plt_type is PID */ > if (!(plt_type & HID_USAGE_PAGE)) { > switch (plt_type) { > case PLT_DA60: > - if (PLT_ALLOW_CONSUMER) > + if (allow_consumer) > goto defaulted; > - goto ignored; > + if (usage->hid == HID_CONSUMER_MUTE) { > + mapped_key = KEY_MICMUTE; > + goto mapped; > + } > + break; > default: > - if (PLT_ALLOW_CONSUMER) > + if (allow_consumer || allow_mute) > goto defaulted; > } > + goto ignored; > } > - /* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */ > - /* 'basic telephony compliant' - allow default consumer page map */ > - else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY && > - (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) { > - if (PLT_ALLOW_CONSUMER) > - goto defaulted; > - } > - /* not 'basic telephony' - apply legacy mapping */ > - /* only map if the field is in the device's primary vendor page */ > - else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) { > + > + /* handle standard consumer control mapping */ > + /* and standard telephony mic mute mapping */ > + if (allow_consumer || allow_mute) > + goto defaulted; > + > + /* handle vendor unique types - plt_type is 0xffa0uuuu or 0xffa2uuuu */ > + /* if not 'basic telephony compliant' - map vendor unique controls */ > + if (!((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY && > + (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) && > + !((field->application ^ plt_type) & HID_USAGE_PAGE)) > switch (usage->hid) { > case PLT1_VOL_UP: > case PLT2_VOL_UP: > @@ -95,8 +99,11 @@ static int plantronics_input_mapping(struct hid_device *hdev, > case PLT2_VOL_DOWN: > mapped_key = KEY_VOLUMEDOWN; > goto mapped; > + case PLT1_MIC_MUTE: > + case PLT2_MIC_MUTE: > + mapped_key = KEY_MICMUTE; > + goto mapped; > } > - } > > /* > * Future mapping of call control or other usages, > @@ -105,6 +112,8 @@ static int plantronics_input_mapping(struct hid_device *hdev, > */ > > ignored: > + hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n", > + usage->hid, field->application); > return -1; > > defaulted: > @@ -123,38 +132,26 @@ static int plantronics_event(struct hid_device *hdev, struct hid_field *field, > struct hid_usage *usage, __s32 value) > { > struct plt_drv_data *drv_data = hid_get_drvdata(hdev); > + unsigned long prev_tsto, cur_ts; > + __u16 prev_key, cur_key; > > - if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) { > - unsigned long prev_ts, cur_ts; > + /* Usages are filtered in plantronics_usages. */ > > - /* Usages are filtered in plantronics_usages. */ > + /* HZ too low for ms resolution - double key detection disabled */ > + /* or it is a key release - handle key presses only. */ > + if (!drv_data->double_key_to || !value) > + return 0; > > - if (!value) /* Handle key presses only. */ > - return 0; > + prev_tsto = drv_data->last_key_ts + drv_data->double_key_to; > + cur_ts = drv_data->last_key_ts = jiffies; > + prev_key = drv_data->last_key; > + cur_key = drv_data->last_key = usage->code; > > - prev_ts = drv_data->last_volume_key_ts; > - cur_ts = jiffies; > - if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_DOUBLE_KEY_TIMEOUT) > - return 1; /* Ignore the repeated key. */ > - > - drv_data->last_volume_key_ts = cur_ts; > + /* If the same key occurs in <= double_key_to -- ignore it */ > + if (prev_key == cur_key && time_before_eq(cur_ts, prev_tsto)) { > + hid_dbg(hdev, "double key %d ignored\n", cur_key); > + return 1; /* Ignore the repeated key. */ > } > - if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) { > - unsigned long prev_ts, cur_ts; > - > - /* Usages are filtered in plantronics_usages. */ > - > - if (!value) /* Handle key presses only. */ > - return 0; > - > - prev_ts = drv_data->last_volume_key_ts; > - cur_ts = jiffies; > - if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT) > - return 1; /* Ignore the followed opposite volume key. */ > - > - drv_data->last_volume_key_ts = cur_ts; > - } > - > return 0; > } > > @@ -196,12 +193,16 @@ static int plantronics_probe(struct hid_device *hdev, > ret = hid_parse(hdev); > if (ret) { > hid_err(hdev, "parse failed\n"); > - goto err; > + return ret; > } > > drv_data->device_type = plantronics_device_type(hdev); > - drv_data->quirks = id->driver_data; > - drv_data->last_volume_key_ts = jiffies - msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT); > + drv_data->double_key_to = msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT); > + drv_data->last_key_ts = jiffies - drv_data->double_key_to; > + > + /* if HZ does not allow ms resolution - disable double key detection */ > + if (drv_data->double_key_to < PLT_DOUBLE_KEY_TIMEOUT) > + drv_data->double_key_to = 0; > > hid_set_drvdata(hdev, drv_data); > > @@ -210,29 +211,10 @@ static int plantronics_probe(struct hid_device *hdev, > if (ret) > hid_err(hdev, "hw start failed\n"); > > -err: > return ret; > } > > static const struct hid_device_id plantronics_devices[] = { > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES), > - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES), > - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES), > - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES), > - .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES), > - .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, > - { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, > - USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES), > - .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS }, > { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, > { } > }; > @@ -241,6 +223,14 @@ MODULE_DEVICE_TABLE(hid, plantronics_devices); > static const struct hid_usage_id plantronics_usages[] = { > { HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID }, > { HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID }, > + { HID_TELEPHONY_MUTE, EV_KEY, HID_ANY_ID }, > + { HID_CONSUMER_MUTE, EV_KEY, HID_ANY_ID }, > + { PLT2_VOL_UP, EV_KEY, HID_ANY_ID }, > + { PLT2_VOL_DOWN, EV_KEY, HID_ANY_ID }, > + { PLT2_MIC_MUTE, EV_KEY, HID_ANY_ID }, > + { PLT1_VOL_UP, EV_KEY, HID_ANY_ID }, > + { PLT1_VOL_DOWN, EV_KEY, HID_ANY_ID }, > + { PLT1_MIC_MUTE, EV_KEY, HID_ANY_ID }, > { HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR } > }; >