xref: /openbmc/linux/drivers/hid/hid-elan.c (revision 314f04e8)
1 /*
2  * HID Driver for ELAN Touchpad
3  *
4  * Currently only supports touchpad found on HP Pavilion X2 10
5  *
6  * Copyright (c) 2016 Alexandrov Stanislav <neko@nya.ai>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
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 #define ELAN_MAX_FINGERS	5
27 #define ELAN_MAX_PRESSURE	255
28 #define ELAN_TP_USB_INTF	1
29 
30 #define ELAN_MUTE_LED_REPORT	0xBC
31 #define ELAN_LED_REPORT_SIZE	8
32 
33 struct elan_touchpad_settings {
34 	u16 max_x;
35 	u16 max_y;
36 };
37 
38 struct elan_drvdata {
39 	struct input_dev *input;
40 	u8 prev_report[ELAN_INPUT_REPORT_SIZE];
41 	struct led_classdev mute_led;
42 	u8 mute_led_state;
43 	struct elan_touchpad_settings *settings;
44 };
45 
46 static int is_not_elan_touchpad(struct hid_device *hdev)
47 {
48 	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
49 
50 	return (intf->altsetting->desc.bInterfaceNumber != ELAN_TP_USB_INTF);
51 }
52 
53 static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54 			      struct hid_field *field, struct hid_usage *usage,
55 			      unsigned long **bit, int *max)
56 {
57 	if (is_not_elan_touchpad(hdev))
58 		return 0;
59 
60 	if (field->report->id == ELAN_SINGLE_FINGER ||
61 	    field->report->id == ELAN_MT_FIRST_FINGER ||
62 	    field->report->id == ELAN_MT_SECOND_FINGER)
63 		return -1;
64 
65 	return 0;
66 }
67 
68 static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
69 {
70 	int ret;
71 	struct input_dev *input;
72 	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
73 
74 	if (is_not_elan_touchpad(hdev))
75 		return 0;
76 
77 	input = devm_input_allocate_device(&hdev->dev);
78 	if (!input)
79 		return -ENOMEM;
80 
81 	input->name = "Elan Touchpad";
82 	input->phys = hdev->phys;
83 	input->uniq = hdev->uniq;
84 	input->id.bustype = hdev->bus;
85 	input->id.vendor  = hdev->vendor;
86 	input->id.product = hdev->product;
87 	input->id.version = hdev->version;
88 	input->dev.parent = &hdev->dev;
89 
90 	input_set_abs_params(input, ABS_MT_POSITION_X, 0,
91 			     drvdata->settings->max_x, 0, 0);
92 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
93 			     drvdata->settings->max_y, 0, 0);
94 	input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE,
95 			     0, 0);
96 
97 	__set_bit(BTN_LEFT, input->keybit);
98 	__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
99 
100 	ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
101 	if (ret) {
102 		hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
103 		return ret;
104 	}
105 
106 	ret = input_register_device(input);
107 	if (ret) {
108 		hid_err(hdev, "Failed to register elan input device: %d\n",
109 			ret);
110 		input_free_device(input);
111 		return ret;
112 	}
113 
114 	drvdata->input = input;
115 
116 	return 0;
117 }
118 
119 static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
120 				unsigned int slot_num)
121 {
122 	struct input_dev *input = drvdata->input;
123 	int x, y, p;
124 
125 	bool active = !!data;
126 
127 	input_mt_slot(input, slot_num);
128 	input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
129 	if (active) {
130 		x = ((data[0] & 0xF0) << 4) | data[1];
131 		y = drvdata->settings->max_y -
132 		    (((data[0] & 0x07) << 8) | data[2]);
133 		p = data[4];
134 
135 		input_report_abs(input, ABS_MT_POSITION_X, x);
136 		input_report_abs(input, ABS_MT_POSITION_Y, y);
137 		input_report_abs(input, ABS_MT_PRESSURE, p);
138 	}
139 }
140 
141 static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
142 {
143 	int i;
144 	struct input_dev *input = drvdata->input;
145 
146 	/*
147 	 * There is 3 types of reports: for single touch,
148 	 * for multitouch - first finger and for multitouch - second finger
149 	 *
150 	 * packet structure for ELAN_SINGLE_FINGER and ELAN_MT_FIRST_FINGER:
151 	 *
152 	 * byte 1: 1   0   0   0   0   0   0   1  // 0x81 or 0x82
153 	 * byte 2: 0   0   0   0   0   0   0   0  // looks like unused
154 	 * byte 3: f5  f4  f3  f2  f1  0   0   L
155 	 * byte 4: x12 x11 x10 x9  0?  y11 y10 y9
156 	 * byte 5: x8  x7  x6  x5  x4  x3  x2  x1
157 	 * byte 6: y8  y7  y6  y5  y4  y3  y2  y1
158 	 * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
159 	 * byte 8: p8  p7  p6  p5  p4  p3  p2  p1
160 	 *
161 	 * packet structure for ELAN_MT_SECOND_FINGER:
162 	 *
163 	 * byte 1: 1   0   0   0   0   0   1   1  // 0x83
164 	 * byte 2: x12 x11 x10 x9  0   y11 y10 y9
165 	 * byte 3: x8  x7  x6  x5  x4  x3  x2  x1
166 	 * byte 4: y8  y7  y6  y5  y4  y3  y2  y1
167 	 * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
168 	 * byte 6: p8  p7  p6  p5  p4  p3  p2  p1
169 	 * byte 7: 0   0   0   0   0   0   0   0
170 	 * byte 8: 0   0   0   0   0   0   0   0
171 	 *
172 	 * f5-f1: finger touch bits
173 	 * L: clickpad button
174 	 * sy / sx: finger width / height expressed in traces, the total number
175 	 *          of traces can be queried by doing a HID_REQ_SET_REPORT
176 	 *          { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the
177 	 *          returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces.
178 	 * p: pressure
179 	 */
180 
181 	if (data[0] == ELAN_SINGLE_FINGER) {
182 		for (i = 0; i < ELAN_MAX_FINGERS; i++) {
183 			if (data[2] & BIT(i + 3))
184 				elan_report_mt_slot(drvdata, data + 3, i);
185 			else
186 				elan_report_mt_slot(drvdata, NULL, i);
187 		}
188 		input_report_key(input, BTN_LEFT, data[2] & 0x01);
189 	}
190 	/*
191 	 * When touched with two fingers Elan touchpad will emit two HID reports
192 	 * first is ELAN_MT_FIRST_FINGER and second is ELAN_MT_SECOND_FINGER
193 	 * we will save ELAN_MT_FIRST_FINGER report and wait for
194 	 * ELAN_MT_SECOND_FINGER to finish multitouch
195 	 */
196 	if (data[0] == ELAN_MT_FIRST_FINGER) {
197 		memcpy(drvdata->prev_report, data,
198 		       sizeof(drvdata->prev_report));
199 		return;
200 	}
201 
202 	if (data[0] == ELAN_MT_SECOND_FINGER) {
203 		int first = 0;
204 		u8 *prev_report = drvdata->prev_report;
205 
206 		if (prev_report[0] != ELAN_MT_FIRST_FINGER)
207 			return;
208 
209 		for (i = 0; i < ELAN_MAX_FINGERS; i++) {
210 			if (prev_report[2] & BIT(i + 3)) {
211 				if (!first) {
212 					first = 1;
213 					elan_report_mt_slot(drvdata, prev_report + 3, i);
214 				} else {
215 					elan_report_mt_slot(drvdata, data + 1, i);
216 				}
217 			} else {
218 				elan_report_mt_slot(drvdata, NULL, i);
219 			}
220 		}
221 		input_report_key(input, BTN_LEFT, prev_report[2] & 0x01);
222 	}
223 
224 	input_mt_sync_frame(input);
225 	input_sync(input);
226 }
227 
228 static int elan_raw_event(struct hid_device *hdev,
229 			  struct hid_report *report, u8 *data, int size)
230 {
231 	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
232 
233 	if (is_not_elan_touchpad(hdev))
234 		return 0;
235 
236 	if (data[0] == ELAN_SINGLE_FINGER ||
237 	    data[0] == ELAN_MT_FIRST_FINGER ||
238 	    data[0] == ELAN_MT_SECOND_FINGER) {
239 		if (size == ELAN_INPUT_REPORT_SIZE) {
240 			elan_report_input(drvdata, data);
241 			return 1;
242 		}
243 	}
244 
245 	return 0;
246 }
247 
248 static int elan_start_multitouch(struct hid_device *hdev)
249 {
250 	int ret;
251 
252 	/*
253 	 * This byte sequence will enable multitouch mode and disable
254 	 * mouse emulation
255 	 */
256 	const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
257 	unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
258 
259 	if (!dmabuf)
260 		return -ENOMEM;
261 
262 	ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
263 				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
264 
265 	kfree(dmabuf);
266 
267 	if (ret != sizeof(buf)) {
268 		hid_err(hdev, "Failed to start multitouch: %d\n", ret);
269 		return ret;
270 	}
271 
272 	return 0;
273 }
274 
275 static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev)
276 {
277 	struct device *dev = led_cdev->dev->parent;
278 	struct hid_device *hdev = to_hid_device(dev);
279 	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
280 
281 	return drvdata->mute_led_state;
282 }
283 
284 static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev,
285 				       enum led_brightness value)
286 {
287 	int ret;
288 	u8 led_state;
289 	struct device *dev = led_cdev->dev->parent;
290 	struct hid_device *hdev = to_hid_device(dev);
291 	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
292 
293 	unsigned char *dmabuf = kzalloc(ELAN_LED_REPORT_SIZE, GFP_KERNEL);
294 
295 	if (!dmabuf)
296 		return -ENOMEM;
297 
298 	led_state = !!value;
299 
300 	dmabuf[0] = ELAN_MUTE_LED_REPORT;
301 	dmabuf[1] = 0x02;
302 	dmabuf[2] = led_state;
303 
304 	ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, ELAN_LED_REPORT_SIZE,
305 				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
306 
307 	kfree(dmabuf);
308 
309 	if (ret != ELAN_LED_REPORT_SIZE) {
310 		hid_err(hdev, "Failed to set mute led brightness: %d\n", ret);
311 		return ret;
312 	}
313 
314 	drvdata->mute_led_state = led_state;
315 	return 0;
316 }
317 
318 static int elan_init_mute_led(struct hid_device *hdev)
319 {
320 	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
321 	struct led_classdev *mute_led = &drvdata->mute_led;
322 
323 	mute_led->name = "elan:red:mute";
324 	mute_led->brightness_get = elan_mute_led_get_brigtness;
325 	mute_led->brightness_set_blocking = elan_mute_led_set_brigtness;
326 	mute_led->max_brightness = LED_ON;
327 	mute_led->dev = &hdev->dev;
328 
329 	return devm_led_classdev_register(&hdev->dev, mute_led);
330 }
331 
332 static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
333 {
334 	int ret;
335 	struct elan_drvdata *drvdata;
336 
337 	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
338 
339 	if (!drvdata)
340 		return -ENOMEM;
341 
342 	drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
343 	hid_set_drvdata(hdev, drvdata);
344 
345 	ret = hid_parse(hdev);
346 	if (ret) {
347 		hid_err(hdev, "Hid Parse failed\n");
348 		return ret;
349 	}
350 
351 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
352 	if (ret) {
353 		hid_err(hdev, "Hid hw start failed\n");
354 		return ret;
355 	}
356 
357 	if (is_not_elan_touchpad(hdev))
358 		return 0;
359 
360 	if (!drvdata->input) {
361 		hid_err(hdev, "Input device is not registred\n");
362 		ret = -ENAVAIL;
363 		goto err;
364 	}
365 
366 	ret = elan_start_multitouch(hdev);
367 	if (ret)
368 		goto err;
369 
370 	ret = elan_init_mute_led(hdev);
371 	if (ret)
372 		goto err;
373 
374 	return 0;
375 err:
376 	hid_hw_stop(hdev);
377 	return ret;
378 }
379 
380 static void elan_remove(struct hid_device *hdev)
381 {
382 	hid_hw_stop(hdev);
383 }
384 
385 static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
386 	.max_x = 2930,
387 	.max_y = 1250,
388 };
389 
390 static const struct hid_device_id elan_devices[] = {
391 	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
392 		(kernel_ulong_t)&hp_x2_10_touchpad_data},
393 	{ }
394 };
395 
396 MODULE_DEVICE_TABLE(hid, elan_devices);
397 
398 static struct hid_driver elan_driver = {
399 	.name = "elan",
400 	.id_table = elan_devices,
401 	.input_mapping = elan_input_mapping,
402 	.input_configured = elan_input_configured,
403 	.raw_event = elan_raw_event,
404 	.probe = elan_probe,
405 	.remove = elan_remove,
406 };
407 
408 module_hid_driver(elan_driver);
409 
410 MODULE_LICENSE("GPL");
411 MODULE_AUTHOR("Alexandrov Stanislav");
412 MODULE_DESCRIPTION("Driver for HID ELAN Touchpads");
413