13
13
14
14
#include <linux/hid.h>
15
15
#include <linux/module.h>
16
+ #include <linux/jiffies.h>
16
17
17
18
#define PLT_HID_1_0_PAGE 0xffa00000
18
19
#define PLT_HID_2_0_PAGE 0xffa20000
36
37
#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \
37
38
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
38
39
40
+ #define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0)
41
+
42
+ #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */
43
+
44
+ struct plt_drv_data {
45
+ unsigned long device_type ;
46
+ unsigned long last_volume_key_ts ;
47
+ u32 quirks ;
48
+ };
49
+
39
50
static int plantronics_input_mapping (struct hid_device * hdev ,
40
51
struct hid_input * hi ,
41
52
struct hid_field * field ,
42
53
struct hid_usage * usage ,
43
54
unsigned long * * bit , int * max )
44
55
{
45
56
unsigned short mapped_key ;
46
- unsigned long plt_type = (unsigned long )hid_get_drvdata (hdev );
57
+ struct plt_drv_data * drv_data = hid_get_drvdata (hdev );
58
+ unsigned long plt_type = drv_data -> device_type ;
47
59
48
60
/* special case for PTT products */
49
61
if (field -> application == HID_GD_JOYSTICK )
@@ -105,6 +117,30 @@ static int plantronics_input_mapping(struct hid_device *hdev,
105
117
return 1 ;
106
118
}
107
119
120
+ static int plantronics_event (struct hid_device * hdev , struct hid_field * field ,
121
+ struct hid_usage * usage , __s32 value )
122
+ {
123
+ struct plt_drv_data * drv_data = hid_get_drvdata (hdev );
124
+
125
+ if (drv_data -> quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS ) {
126
+ unsigned long prev_ts , cur_ts ;
127
+
128
+ /* Usages are filtered in plantronics_usages. */
129
+
130
+ if (!value ) /* Handle key presses only. */
131
+ return 0 ;
132
+
133
+ prev_ts = drv_data -> last_volume_key_ts ;
134
+ cur_ts = jiffies ;
135
+ if (jiffies_to_msecs (cur_ts - prev_ts ) <= PLT_DOUBLE_KEY_TIMEOUT )
136
+ return 1 ; /* Ignore the repeated key. */
137
+
138
+ drv_data -> last_volume_key_ts = cur_ts ;
139
+ }
140
+
141
+ return 0 ;
142
+ }
143
+
108
144
static unsigned long plantronics_device_type (struct hid_device * hdev )
109
145
{
110
146
unsigned i , col_page ;
@@ -133,15 +169,24 @@ static unsigned long plantronics_device_type(struct hid_device *hdev)
133
169
static int plantronics_probe (struct hid_device * hdev ,
134
170
const struct hid_device_id * id )
135
171
{
172
+ struct plt_drv_data * drv_data ;
136
173
int ret ;
137
174
175
+ drv_data = devm_kzalloc (& hdev -> dev , sizeof (* drv_data ), GFP_KERNEL );
176
+ if (!drv_data )
177
+ return - ENOMEM ;
178
+
138
179
ret = hid_parse (hdev );
139
180
if (ret ) {
140
181
hid_err (hdev , "parse failed\n" );
141
182
goto err ;
142
183
}
143
184
144
- hid_set_drvdata (hdev , (void * )plantronics_device_type (hdev ));
185
+ drv_data -> device_type = plantronics_device_type (hdev );
186
+ drv_data -> quirks = id -> driver_data ;
187
+ drv_data -> last_volume_key_ts = jiffies - msecs_to_jiffies (PLT_DOUBLE_KEY_TIMEOUT );
188
+
189
+ hid_set_drvdata (hdev , drv_data );
145
190
146
191
ret = hid_hw_start (hdev , HID_CONNECT_DEFAULT |
147
192
HID_CONNECT_HIDINPUT_FORCE | HID_CONNECT_HIDDEV_FORCE );
@@ -153,15 +198,26 @@ static int plantronics_probe(struct hid_device *hdev,
153
198
}
154
199
155
200
static const struct hid_device_id plantronics_devices [] = {
201
+ { HID_USB_DEVICE (USB_VENDOR_ID_PLANTRONICS ,
202
+ USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES ),
203
+ .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
156
204
{ HID_USB_DEVICE (USB_VENDOR_ID_PLANTRONICS , HID_ANY_ID ) },
157
205
{ }
158
206
};
159
207
MODULE_DEVICE_TABLE (hid , plantronics_devices );
160
208
209
+ static const struct hid_usage_id plantronics_usages [] = {
210
+ { HID_CP_VOLUMEUP , EV_KEY , HID_ANY_ID },
211
+ { HID_CP_VOLUMEDOWN , EV_KEY , HID_ANY_ID },
212
+ { HID_TERMINATOR , HID_TERMINATOR , HID_TERMINATOR }
213
+ };
214
+
161
215
static struct hid_driver plantronics_driver = {
162
216
.name = "plantronics" ,
163
217
.id_table = plantronics_devices ,
218
+ .usage_table = plantronics_usages ,
164
219
.input_mapping = plantronics_input_mapping ,
220
+ .event = plantronics_event ,
165
221
.probe = plantronics_probe ,
166
222
};
167
223
module_hid_driver (plantronics_driver );
0 commit comments