1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/hid.h>
15#include <linux/input/mt.h>
16#include <linux/leds.h>
17#include <linux/module.h>
18#include <linux/usb.h>
19
20#include "hid-ids.h"
21
22#define ELAN_SINGLE_FINGER 0x81
23#define ELAN_MT_FIRST_FINGER 0x82
24#define ELAN_MT_SECOND_FINGER 0x83
25#define ELAN_INPUT_REPORT_SIZE 8
26
27#define ELAN_MUTE_LED_REPORT 0xBC
28#define ELAN_LED_REPORT_SIZE 8
29
30struct elan_touchpad_settings {
31 u8 max_fingers;
32 u16 max_x;
33 u16 max_y;
34 u8 max_area_x;
35 u8 max_area_y;
36 u8 max_w;
37 int usb_bInterfaceNumber;
38};
39
40struct elan_drvdata {
41 struct input_dev *input;
42 u8 prev_report[ELAN_INPUT_REPORT_SIZE];
43 struct led_classdev mute_led;
44 u8 mute_led_state;
45 struct elan_touchpad_settings *settings;
46};
47
48static int is_not_elan_touchpad(struct hid_device *hdev)
49{
50 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
51 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
52
53 return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
54}
55
56static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
57 struct hid_field *field, struct hid_usage *usage,
58 unsigned long **bit, int *max)
59{
60 if (is_not_elan_touchpad(hdev))
61 return 0;
62
63 if (field->report->id == ELAN_SINGLE_FINGER ||
64 field->report->id == ELAN_MT_FIRST_FINGER ||
65 field->report->id == ELAN_MT_SECOND_FINGER)
66 return -1;
67
68 return 0;
69}
70
71static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
72{
73 int ret;
74 struct input_dev *input;
75 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
76
77 if (is_not_elan_touchpad(hdev))
78 return 0;
79
80 input = devm_input_allocate_device(&hdev->dev);
81 if (!input)
82 return -ENOMEM;
83
84 input->name = "Elan Touchpad";
85 input->phys = hdev->phys;
86 input->uniq = hdev->uniq;
87 input->id.bustype = hdev->bus;
88 input->id.vendor = hdev->vendor;
89 input->id.product = hdev->product;
90 input->id.version = hdev->version;
91 input->dev.parent = &hdev->dev;
92
93 input_set_abs_params(input, ABS_MT_POSITION_X, 0,
94 drvdata->settings->max_x, 0, 0);
95 input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
96 drvdata->settings->max_y, 0, 0);
97 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
98 drvdata->settings->max_fingers, 0, 0);
99 input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
100 drvdata->settings->max_w, 0, 0);
101
102 __set_bit(BTN_LEFT, input->keybit);
103 __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
104
105 ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
106 INPUT_MT_POINTER);
107 if (ret) {
108 hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
109 return ret;
110 }
111
112 ret = input_register_device(input);
113 if (ret) {
114 hid_err(hdev, "Failed to register elan input device: %d\n",
115 ret);
116 input_free_device(input);
117 return ret;
118 }
119
120 drvdata->input = input;
121
122 return 0;
123}
124
125static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
126 unsigned int slot_num)
127{
128 struct input_dev *input = drvdata->input;
129 int x, y, w;
130
131 bool active = !!data;
132
133 input_mt_slot(input, slot_num);
134 input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
135 if (active) {
136 x = ((data[0] & 0xF0) << 4) | data[1];
137 y = drvdata->settings->max_y -
138 (((data[0] & 0x07) << 8) | data[2]);
139 w = data[4];
140
141 input_report_abs(input, ABS_MT_POSITION_X, x);
142 input_report_abs(input, ABS_MT_POSITION_Y, y);
143 input_report_abs(input, ABS_TOOL_WIDTH, w);
144 }
145}
146
147static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
148{
149 int i;
150 struct input_dev *input = drvdata->input;
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 if (data[0] == ELAN_SINGLE_FINGER) {
186 for (i = 0; i < drvdata->settings->max_fingers; i++) {
187 if (data[2] & BIT(i + 3))
188 elan_report_mt_slot(drvdata, data + 3, i);
189 else
190 elan_report_mt_slot(drvdata, NULL, i);
191 }
192 input_report_key(input, BTN_LEFT, data[2] & 0x01);
193 }
194
195
196
197
198
199
200 if (data[0] == ELAN_MT_FIRST_FINGER) {
201 memcpy(drvdata->prev_report, data,
202 sizeof(drvdata->prev_report));
203 return;
204 }
205
206 if (data[0] == ELAN_MT_SECOND_FINGER) {
207 int first = 0;
208 u8 *prev_report = drvdata->prev_report;
209
210 if (prev_report[0] != ELAN_MT_FIRST_FINGER)
211 return;
212
213 for (i = 0; i < drvdata->settings->max_fingers; i++) {
214 if (prev_report[2] & BIT(i + 3)) {
215 if (!first) {
216 first = 1;
217 elan_report_mt_slot(drvdata, prev_report + 3, i);
218 } else {
219 elan_report_mt_slot(drvdata, data + 1, i);
220 }
221 } else {
222 elan_report_mt_slot(drvdata, NULL, i);
223 }
224 }
225 input_report_key(input, BTN_LEFT, prev_report[2] & 0x01);
226 }
227
228 input_mt_sync_frame(input);
229 input_sync(input);
230}
231
232static int elan_raw_event(struct hid_device *hdev,
233 struct hid_report *report, u8 *data, int size)
234{
235 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
236
237 if (is_not_elan_touchpad(hdev))
238 return 0;
239
240 if (data[0] == ELAN_SINGLE_FINGER ||
241 data[0] == ELAN_MT_FIRST_FINGER ||
242 data[0] == ELAN_MT_SECOND_FINGER) {
243 if (size == ELAN_INPUT_REPORT_SIZE) {
244 elan_report_input(drvdata, data);
245 return 1;
246 }
247 }
248
249 return 0;
250}
251
252static int elan_start_multitouch(struct hid_device *hdev)
253{
254 int ret;
255
256
257
258
259
260 const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
261 unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
262
263 if (!dmabuf)
264 return -ENOMEM;
265
266 ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
267 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
268
269 kfree(dmabuf);
270
271 if (ret != sizeof(buf)) {
272 hid_err(hdev, "Failed to start multitouch: %d\n", ret);
273 return ret;
274 }
275
276 return 0;
277}
278
279static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev)
280{
281 struct device *dev = led_cdev->dev->parent;
282 struct hid_device *hdev = to_hid_device(dev);
283 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
284
285 return drvdata->mute_led_state;
286}
287
288static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev,
289 enum led_brightness value)
290{
291 int ret;
292 u8 led_state;
293 struct device *dev = led_cdev->dev->parent;
294 struct hid_device *hdev = to_hid_device(dev);
295 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
296
297 unsigned char *dmabuf = kzalloc(ELAN_LED_REPORT_SIZE, GFP_KERNEL);
298
299 if (!dmabuf)
300 return -ENOMEM;
301
302 led_state = !!value;
303
304 dmabuf[0] = ELAN_MUTE_LED_REPORT;
305 dmabuf[1] = 0x02;
306 dmabuf[2] = led_state;
307
308 ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, ELAN_LED_REPORT_SIZE,
309 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
310
311 kfree(dmabuf);
312
313 if (ret != ELAN_LED_REPORT_SIZE) {
314 hid_err(hdev, "Failed to set mute led brightness: %d\n", ret);
315 return ret;
316 }
317
318 drvdata->mute_led_state = led_state;
319 return 0;
320}
321
322static int elan_init_mute_led(struct hid_device *hdev)
323{
324 struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
325 struct led_classdev *mute_led = &drvdata->mute_led;
326
327 mute_led->name = "elan:red:mute";
328 mute_led->brightness_get = elan_mute_led_get_brigtness;
329 mute_led->brightness_set_blocking = elan_mute_led_set_brigtness;
330 mute_led->max_brightness = LED_ON;
331 mute_led->dev = &hdev->dev;
332
333 return devm_led_classdev_register(&hdev->dev, mute_led);
334}
335
336static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
337{
338 int ret;
339 struct elan_drvdata *drvdata;
340
341 drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
342
343 if (!drvdata)
344 return -ENOMEM;
345
346 drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
347 hid_set_drvdata(hdev, drvdata);
348
349 ret = hid_parse(hdev);
350 if (ret) {
351 hid_err(hdev, "Hid Parse failed\n");
352 return ret;
353 }
354
355 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
356 if (ret) {
357 hid_err(hdev, "Hid hw start failed\n");
358 return ret;
359 }
360
361 if (is_not_elan_touchpad(hdev))
362 return 0;
363
364 if (!drvdata->input) {
365 hid_err(hdev, "Input device is not registred\n");
366 ret = -ENAVAIL;
367 goto err;
368 }
369
370 ret = elan_start_multitouch(hdev);
371 if (ret)
372 goto err;
373
374 ret = elan_init_mute_led(hdev);
375 if (ret)
376 goto err;
377
378 return 0;
379err:
380 hid_hw_stop(hdev);
381 return ret;
382}
383
384static void elan_remove(struct hid_device *hdev)
385{
386 hid_hw_stop(hdev);
387}
388
389static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
390 .max_fingers = 5,
391 .max_x = 2930,
392 .max_y = 1250,
393 .max_area_x = 15,
394 .max_area_y = 15,
395 .max_w = 255,
396 .usb_bInterfaceNumber = 1,
397};
398
399static const struct hid_device_id elan_devices[] = {
400 { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
401 (kernel_ulong_t)&hp_x2_10_touchpad_data},
402 { }
403};
404
405MODULE_DEVICE_TABLE(hid, elan_devices);
406
407static struct hid_driver elan_driver = {
408 .name = "elan",
409 .id_table = elan_devices,
410 .input_mapping = elan_input_mapping,
411 .input_configured = elan_input_configured,
412 .raw_event = elan_raw_event,
413 .probe = elan_probe,
414 .remove = elan_remove,
415};
416
417module_hid_driver(elan_driver);
418
419MODULE_LICENSE("GPL");
420MODULE_AUTHOR("Alexandrov Stanislav");
421MODULE_DESCRIPTION("Driver for HID ELAN Touchpads");
422