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