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 }
> };
>
[Index of Archives]
[Pulseaudio]
[Linux Audio Users]
[ALSA Devel]
[Fedora Desktop]
[Fedora SELinux]
[Big List of Linux Books]
[Yosemite News]
[KDE Users]