261 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Plantronics USB HID Driver4 *5 * Copyright (c) 2014 JD Cole <jd.cole@plantronics.com>6 * Copyright (c) 2015-2018 Terry Junge <terry.junge@plantronics.com>7 */8 9/*10 */11 12#include "hid-ids.h"13 14#include <linux/hid.h>15#include <linux/module.h>16#include <linux/jiffies.h>17 18#define PLT_HID_1_0_PAGE 0xffa0000019#define PLT_HID_2_0_PAGE 0xffa2000020 21#define PLT_BASIC_TELEPHONY 0x000322#define PLT_BASIC_EXCEPTION 0x000523 24#define PLT_VOL_UP 0x00b125#define PLT_VOL_DOWN 0x00b226 27#define PLT1_VOL_UP (PLT_HID_1_0_PAGE | PLT_VOL_UP)28#define PLT1_VOL_DOWN (PLT_HID_1_0_PAGE | PLT_VOL_DOWN)29#define PLT2_VOL_UP (PLT_HID_2_0_PAGE | PLT_VOL_UP)30#define PLT2_VOL_DOWN (PLT_HID_2_0_PAGE | PLT_VOL_DOWN)31 32#define PLT_DA60 0xda6033#define PLT_BT300_MIN 0x041334#define PLT_BT300_MAX 0x041835 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 43#define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */44#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */45 46struct plt_drv_data {47 unsigned long device_type;48 unsigned long last_volume_key_ts;49 u32 quirks;50};51 52static int plantronics_input_mapping(struct hid_device *hdev,53 struct hid_input *hi,54 struct hid_field *field,55 struct hid_usage *usage,56 unsigned long **bit, int *max)57{58 unsigned short mapped_key;59 struct plt_drv_data *drv_data = hid_get_drvdata(hdev);60 unsigned long plt_type = drv_data->device_type;61 62 /* special case for PTT products */63 if (field->application == HID_GD_JOYSTICK)64 goto defaulted;65 66 /* handle volume up/down mapping */67 /* non-standard types or multi-HID interfaces - plt_type is PID */68 if (!(plt_type & HID_USAGE_PAGE)) {69 switch (plt_type) {70 case PLT_DA60:71 if (PLT_ALLOW_CONSUMER)72 goto defaulted;73 goto ignored;74 default:75 if (PLT_ALLOW_CONSUMER)76 goto defaulted;77 }78 }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)) {89 switch (usage->hid) {90 case PLT1_VOL_UP:91 case PLT2_VOL_UP:92 mapped_key = KEY_VOLUMEUP;93 goto mapped;94 case PLT1_VOL_DOWN:95 case PLT2_VOL_DOWN:96 mapped_key = KEY_VOLUMEDOWN;97 goto mapped;98 }99 }100 101/*102 * Future mapping of call control or other usages,103 * if and when keys are defined would go here104 * otherwise, ignore everything else that was not mapped105 */106 107ignored:108 return -1;109 110defaulted:111 hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n",112 usage->hid, field->application);113 return 0;114 115mapped:116 hid_map_usage_clear(hi, usage, bit, max, EV_KEY, mapped_key);117 hid_dbg(hdev, "usage: %08x (appl: %08x) - mapped to key %d\n",118 usage->hid, field->application, mapped_key);119 return 1;120}121 122static int plantronics_event(struct hid_device *hdev, struct hid_field *field,123 struct hid_usage *usage, __s32 value)124{125 struct plt_drv_data *drv_data = hid_get_drvdata(hdev);126 127 if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) {128 unsigned long prev_ts, cur_ts;129 130 /* Usages are filtered in plantronics_usages. */131 132 if (!value) /* Handle key presses only. */133 return 0;134 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;141 }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 158 return 0;159}160 161static unsigned long plantronics_device_type(struct hid_device *hdev)162{163 unsigned i, col_page;164 unsigned long plt_type = hdev->product;165 166 /* multi-HID interfaces? - plt_type is PID */167 if (plt_type >= PLT_BT300_MIN && plt_type <= PLT_BT300_MAX)168 goto exit;169 170 /* determine primary vendor page */171 for (i = 0; i < hdev->maxcollection; i++) {172 col_page = hdev->collection[i].usage & HID_USAGE_PAGE;173 if (col_page == PLT_HID_2_0_PAGE) {174 plt_type = hdev->collection[i].usage;175 break;176 }177 if (col_page == PLT_HID_1_0_PAGE)178 plt_type = hdev->collection[i].usage;179 }180 181exit:182 hid_dbg(hdev, "plt_type decoded as: %08lx\n", plt_type);183 return plt_type;184}185 186static int plantronics_probe(struct hid_device *hdev,187 const struct hid_device_id *id)188{189 struct plt_drv_data *drv_data;190 int ret;191 192 drv_data = devm_kzalloc(&hdev->dev, sizeof(*drv_data), GFP_KERNEL);193 if (!drv_data)194 return -ENOMEM;195 196 ret = hid_parse(hdev);197 if (ret) {198 hid_err(hdev, "parse failed\n");199 goto err;200 }201 202 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);205 206 hid_set_drvdata(hdev, drv_data);207 208 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |209 HID_CONNECT_HIDINPUT_FORCE | HID_CONNECT_HIDDEV_FORCE);210 if (ret)211 hid_err(hdev, "hw start failed\n");212 213err:214 return ret;215}216 217static 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 },236 { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },237 { }238};239MODULE_DEVICE_TABLE(hid, plantronics_devices);240 241static const struct hid_usage_id plantronics_usages[] = {242 { HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID },243 { HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID },244 { HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR }245};246 247static struct hid_driver plantronics_driver = {248 .name = "plantronics",249 .id_table = plantronics_devices,250 .usage_table = plantronics_usages,251 .input_mapping = plantronics_input_mapping,252 .event = plantronics_event,253 .probe = plantronics_probe,254};255module_hid_driver(plantronics_driver);256 257MODULE_AUTHOR("JD Cole <jd.cole@plantronics.com>");258MODULE_AUTHOR("Terry Junge <terry.junge@plantronics.com>");259MODULE_DESCRIPTION("Plantronics USB HID Driver");260MODULE_LICENSE("GPL");261