diff options
author | Jiri Kosina <jkosina@suse.cz> | 2018-08-20 12:06:30 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2018-08-20 12:06:30 -0400 |
commit | 5a12d86ce3a93b6442963e5f6e6511e8f470f760 (patch) | |
tree | cf455374db907523bc95ccd4027fea65ab912f68 | |
parent | 415d2b3392d7a80903e0f97f051201aa02bf20e9 (diff) | |
parent | e7ad3dc9f4a2a183f275c9a3becd0cdd5f69792e (diff) |
Merge branch 'for-4.19/elan' into for-linus
Resolution/pressure fixes and new device support for hid-elan
-rw-r--r-- | drivers/hid/hid-elan.c | 235 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 2 |
2 files changed, 184 insertions, 53 deletions
diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c index 803a725785cf..07e26c3567eb 100644 --- a/drivers/hid/hid-elan.c +++ b/drivers/hid/hid-elan.c | |||
@@ -19,38 +19,49 @@ | |||
19 | 19 | ||
20 | #include "hid-ids.h" | 20 | #include "hid-ids.h" |
21 | 21 | ||
22 | #define ELAN_MT_I2C 0x5d | ||
22 | #define ELAN_SINGLE_FINGER 0x81 | 23 | #define ELAN_SINGLE_FINGER 0x81 |
23 | #define ELAN_MT_FIRST_FINGER 0x82 | 24 | #define ELAN_MT_FIRST_FINGER 0x82 |
24 | #define ELAN_MT_SECOND_FINGER 0x83 | 25 | #define ELAN_MT_SECOND_FINGER 0x83 |
25 | #define ELAN_INPUT_REPORT_SIZE 8 | 26 | #define ELAN_INPUT_REPORT_SIZE 8 |
27 | #define ELAN_I2C_REPORT_SIZE 32 | ||
28 | #define ELAN_FINGER_DATA_LEN 5 | ||
29 | #define ELAN_MAX_FINGERS 5 | ||
30 | #define ELAN_MAX_PRESSURE 255 | ||
31 | #define ELAN_TP_USB_INTF 1 | ||
32 | |||
33 | #define ELAN_FEATURE_REPORT 0x0d | ||
34 | #define ELAN_FEATURE_SIZE 5 | ||
35 | #define ELAN_PARAM_MAX_X 6 | ||
36 | #define ELAN_PARAM_MAX_Y 7 | ||
37 | #define ELAN_PARAM_RES 8 | ||
26 | 38 | ||
27 | #define ELAN_MUTE_LED_REPORT 0xBC | 39 | #define ELAN_MUTE_LED_REPORT 0xBC |
28 | #define ELAN_LED_REPORT_SIZE 8 | 40 | #define ELAN_LED_REPORT_SIZE 8 |
29 | 41 | ||
30 | struct elan_touchpad_settings { | 42 | #define ELAN_HAS_LED BIT(0) |
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 | 43 | ||
40 | struct elan_drvdata { | 44 | struct elan_drvdata { |
41 | struct input_dev *input; | 45 | struct input_dev *input; |
42 | u8 prev_report[ELAN_INPUT_REPORT_SIZE]; | 46 | u8 prev_report[ELAN_INPUT_REPORT_SIZE]; |
43 | struct led_classdev mute_led; | 47 | struct led_classdev mute_led; |
44 | u8 mute_led_state; | 48 | u8 mute_led_state; |
45 | struct elan_touchpad_settings *settings; | 49 | u16 max_x; |
50 | u16 max_y; | ||
51 | u16 res_x; | ||
52 | u16 res_y; | ||
46 | }; | 53 | }; |
47 | 54 | ||
48 | static int is_not_elan_touchpad(struct hid_device *hdev) | 55 | static int is_not_elan_touchpad(struct hid_device *hdev) |
49 | { | 56 | { |
50 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | 57 | if (hdev->bus == BUS_USB) { |
51 | struct elan_drvdata *drvdata = hid_get_drvdata(hdev); | 58 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
59 | |||
60 | return (intf->altsetting->desc.bInterfaceNumber != | ||
61 | ELAN_TP_USB_INTF); | ||
62 | } | ||
52 | 63 | ||
53 | return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber); | 64 | return 0; |
54 | } | 65 | } |
55 | 66 | ||
56 | static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 67 | static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
@@ -62,12 +73,86 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
62 | 73 | ||
63 | if (field->report->id == ELAN_SINGLE_FINGER || | 74 | if (field->report->id == ELAN_SINGLE_FINGER || |
64 | field->report->id == ELAN_MT_FIRST_FINGER || | 75 | field->report->id == ELAN_MT_FIRST_FINGER || |
65 | field->report->id == ELAN_MT_SECOND_FINGER) | 76 | field->report->id == ELAN_MT_SECOND_FINGER || |
77 | field->report->id == ELAN_MT_I2C) | ||
66 | return -1; | 78 | return -1; |
67 | 79 | ||
68 | return 0; | 80 | return 0; |
69 | } | 81 | } |
70 | 82 | ||
83 | static int elan_get_device_param(struct hid_device *hdev, | ||
84 | unsigned char *dmabuf, unsigned char param) | ||
85 | { | ||
86 | int ret; | ||
87 | |||
88 | dmabuf[0] = ELAN_FEATURE_REPORT; | ||
89 | dmabuf[1] = 0x05; | ||
90 | dmabuf[2] = 0x03; | ||
91 | dmabuf[3] = param; | ||
92 | dmabuf[4] = 0x01; | ||
93 | |||
94 | ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf, | ||
95 | ELAN_FEATURE_SIZE, HID_FEATURE_REPORT, | ||
96 | HID_REQ_SET_REPORT); | ||
97 | if (ret != ELAN_FEATURE_SIZE) { | ||
98 | hid_err(hdev, "Set report error for parm %d: %d\n", param, ret); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf, | ||
103 | ELAN_FEATURE_SIZE, HID_FEATURE_REPORT, | ||
104 | HID_REQ_GET_REPORT); | ||
105 | if (ret != ELAN_FEATURE_SIZE) { | ||
106 | hid_err(hdev, "Get report error for parm %d: %d\n", param, ret); | ||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static unsigned int elan_convert_res(char val) | ||
114 | { | ||
115 | /* | ||
116 | * (value from firmware) * 10 + 790 = dpi | ||
117 | * dpi * 10 / 254 = dots/mm | ||
118 | */ | ||
119 | return (val * 10 + 790) * 10 / 254; | ||
120 | } | ||
121 | |||
122 | static int elan_get_device_params(struct hid_device *hdev) | ||
123 | { | ||
124 | struct elan_drvdata *drvdata = hid_get_drvdata(hdev); | ||
125 | unsigned char *dmabuf; | ||
126 | int ret; | ||
127 | |||
128 | dmabuf = kmalloc(ELAN_FEATURE_SIZE, GFP_KERNEL); | ||
129 | if (!dmabuf) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_X); | ||
133 | if (ret) | ||
134 | goto err; | ||
135 | |||
136 | drvdata->max_x = (dmabuf[4] << 8) | dmabuf[3]; | ||
137 | |||
138 | ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_Y); | ||
139 | if (ret) | ||
140 | goto err; | ||
141 | |||
142 | drvdata->max_y = (dmabuf[4] << 8) | dmabuf[3]; | ||
143 | |||
144 | ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_RES); | ||
145 | if (ret) | ||
146 | goto err; | ||
147 | |||
148 | drvdata->res_x = elan_convert_res(dmabuf[3]); | ||
149 | drvdata->res_y = elan_convert_res(dmabuf[4]); | ||
150 | |||
151 | err: | ||
152 | kfree(dmabuf); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
71 | static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) | 156 | static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) |
72 | { | 157 | { |
73 | int ret; | 158 | int ret; |
@@ -77,6 +162,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
77 | if (is_not_elan_touchpad(hdev)) | 162 | if (is_not_elan_touchpad(hdev)) |
78 | return 0; | 163 | return 0; |
79 | 164 | ||
165 | ret = elan_get_device_params(hdev); | ||
166 | if (ret) | ||
167 | return ret; | ||
168 | |||
80 | input = devm_input_allocate_device(&hdev->dev); | 169 | input = devm_input_allocate_device(&hdev->dev); |
81 | if (!input) | 170 | if (!input) |
82 | return -ENOMEM; | 171 | return -ENOMEM; |
@@ -90,25 +179,25 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
90 | input->id.version = hdev->version; | 179 | input->id.version = hdev->version; |
91 | input->dev.parent = &hdev->dev; | 180 | input->dev.parent = &hdev->dev; |
92 | 181 | ||
93 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | 182 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, drvdata->max_x, |
94 | drvdata->settings->max_x, 0, 0); | 183 | 0, 0); |
95 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | 184 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, drvdata->max_y, |
96 | drvdata->settings->max_y, 0, 0); | 185 | 0, 0); |
97 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, | 186 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE, |
98 | drvdata->settings->max_fingers, 0, 0); | 187 | 0, 0); |
99 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, | ||
100 | drvdata->settings->max_w, 0, 0); | ||
101 | 188 | ||
102 | __set_bit(BTN_LEFT, input->keybit); | 189 | __set_bit(BTN_LEFT, input->keybit); |
103 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | 190 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
104 | 191 | ||
105 | ret = input_mt_init_slots(input, drvdata->settings->max_fingers, | 192 | ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER); |
106 | INPUT_MT_POINTER); | ||
107 | if (ret) { | 193 | if (ret) { |
108 | hid_err(hdev, "Failed to init elan MT slots: %d\n", ret); | 194 | hid_err(hdev, "Failed to init elan MT slots: %d\n", ret); |
109 | return ret; | 195 | return ret; |
110 | } | 196 | } |
111 | 197 | ||
198 | input_abs_set_res(input, ABS_X, drvdata->res_x); | ||
199 | input_abs_set_res(input, ABS_Y, drvdata->res_y); | ||
200 | |||
112 | ret = input_register_device(input); | 201 | ret = input_register_device(input); |
113 | if (ret) { | 202 | if (ret) { |
114 | hid_err(hdev, "Failed to register elan input device: %d\n", | 203 | hid_err(hdev, "Failed to register elan input device: %d\n", |
@@ -126,7 +215,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data, | |||
126 | unsigned int slot_num) | 215 | unsigned int slot_num) |
127 | { | 216 | { |
128 | struct input_dev *input = drvdata->input; | 217 | struct input_dev *input = drvdata->input; |
129 | int x, y, w; | 218 | int x, y, p; |
130 | 219 | ||
131 | bool active = !!data; | 220 | bool active = !!data; |
132 | 221 | ||
@@ -134,17 +223,17 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data, | |||
134 | input_mt_report_slot_state(input, MT_TOOL_FINGER, active); | 223 | input_mt_report_slot_state(input, MT_TOOL_FINGER, active); |
135 | if (active) { | 224 | if (active) { |
136 | x = ((data[0] & 0xF0) << 4) | data[1]; | 225 | x = ((data[0] & 0xF0) << 4) | data[1]; |
137 | y = drvdata->settings->max_y - | 226 | y = drvdata->max_y - |
138 | (((data[0] & 0x07) << 8) | data[2]); | 227 | (((data[0] & 0x07) << 8) | data[2]); |
139 | w = data[4]; | 228 | p = data[4]; |
140 | 229 | ||
141 | input_report_abs(input, ABS_MT_POSITION_X, x); | 230 | input_report_abs(input, ABS_MT_POSITION_X, x); |
142 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 231 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
143 | input_report_abs(input, ABS_TOOL_WIDTH, w); | 232 | input_report_abs(input, ABS_MT_PRESSURE, p); |
144 | } | 233 | } |
145 | } | 234 | } |
146 | 235 | ||
147 | static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) | 236 | static void elan_usb_report_input(struct elan_drvdata *drvdata, u8 *data) |
148 | { | 237 | { |
149 | int i; | 238 | int i; |
150 | struct input_dev *input = drvdata->input; | 239 | struct input_dev *input = drvdata->input; |
@@ -162,7 +251,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) | |||
162 | * byte 5: x8 x7 x6 x5 x4 x3 x2 x1 | 251 | * byte 5: x8 x7 x6 x5 x4 x3 x2 x1 |
163 | * byte 6: y8 y7 y6 y5 y4 y3 y2 y1 | 252 | * byte 6: y8 y7 y6 y5 y4 y3 y2 y1 |
164 | * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 | 253 | * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 |
165 | * byte 8: w8 w7 w6 w5 w4 w3 w2 w1 | 254 | * byte 8: p8 p7 p6 p5 p4 p3 p2 p1 |
166 | * | 255 | * |
167 | * packet structure for ELAN_MT_SECOND_FINGER: | 256 | * packet structure for ELAN_MT_SECOND_FINGER: |
168 | * | 257 | * |
@@ -171,19 +260,21 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) | |||
171 | * byte 3: x8 x7 x6 x5 x4 x3 x2 x1 | 260 | * byte 3: x8 x7 x6 x5 x4 x3 x2 x1 |
172 | * byte 4: y8 y7 y6 y5 y4 y3 y2 y1 | 261 | * byte 4: y8 y7 y6 y5 y4 y3 y2 y1 |
173 | * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 | 262 | * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 |
174 | * byte 6: w8 w7 w6 w5 w4 w3 w2 w1 | 263 | * byte 6: p8 p7 p6 p5 p4 p3 p2 p1 |
175 | * byte 7: 0 0 0 0 0 0 0 0 | 264 | * byte 7: 0 0 0 0 0 0 0 0 |
176 | * byte 8: 0 0 0 0 0 0 0 0 | 265 | * byte 8: 0 0 0 0 0 0 0 0 |
177 | * | 266 | * |
178 | * f5-f1: finger touch bits | 267 | * f5-f1: finger touch bits |
179 | * L: clickpad button | 268 | * L: clickpad button |
180 | * sy / sx: not sure yet, but this looks like rectangular | 269 | * sy / sx: finger width / height expressed in traces, the total number |
181 | * area for finger | 270 | * of traces can be queried by doing a HID_REQ_SET_REPORT |
182 | * w: looks like finger width | 271 | * { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the |
272 | * returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces. | ||
273 | * p: pressure | ||
183 | */ | 274 | */ |
184 | 275 | ||
185 | if (data[0] == ELAN_SINGLE_FINGER) { | 276 | if (data[0] == ELAN_SINGLE_FINGER) { |
186 | for (i = 0; i < drvdata->settings->max_fingers; i++) { | 277 | for (i = 0; i < ELAN_MAX_FINGERS; i++) { |
187 | if (data[2] & BIT(i + 3)) | 278 | if (data[2] & BIT(i + 3)) |
188 | elan_report_mt_slot(drvdata, data + 3, i); | 279 | elan_report_mt_slot(drvdata, data + 3, i); |
189 | else | 280 | else |
@@ -210,7 +301,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) | |||
210 | if (prev_report[0] != ELAN_MT_FIRST_FINGER) | 301 | if (prev_report[0] != ELAN_MT_FIRST_FINGER) |
211 | return; | 302 | return; |
212 | 303 | ||
213 | for (i = 0; i < drvdata->settings->max_fingers; i++) { | 304 | for (i = 0; i < ELAN_MAX_FINGERS; i++) { |
214 | if (prev_report[2] & BIT(i + 3)) { | 305 | if (prev_report[2] & BIT(i + 3)) { |
215 | if (!first) { | 306 | if (!first) { |
216 | first = 1; | 307 | first = 1; |
@@ -229,6 +320,46 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) | |||
229 | input_sync(input); | 320 | input_sync(input); |
230 | } | 321 | } |
231 | 322 | ||
323 | static void elan_i2c_report_input(struct elan_drvdata *drvdata, u8 *data) | ||
324 | { | ||
325 | struct input_dev *input = drvdata->input; | ||
326 | u8 *finger_data; | ||
327 | int i; | ||
328 | |||
329 | /* | ||
330 | * Elan MT touchpads in i2c mode send finger data in the same format | ||
331 | * as in USB mode, but then with all fingers in a single packet. | ||
332 | * | ||
333 | * packet structure for ELAN_MT_I2C: | ||
334 | * | ||
335 | * byte 1: 1 0 0 1 1 1 0 1 // 0x5d | ||
336 | * byte 2: f5 f4 f3 f2 f1 0 0 L | ||
337 | * byte 3: x12 x11 x10 x9 0? y11 y10 y9 | ||
338 | * byte 4: x8 x7 x6 x5 x4 x3 x2 x1 | ||
339 | * byte 5: y8 y7 y6 y5 y4 y3 y2 y1 | ||
340 | * byte 6: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 | ||
341 | * byte 7: p8 p7 p6 p5 p4 p3 p2 p1 | ||
342 | * byte 8-12: Same as byte 3-7 for second finger down | ||
343 | * byte 13-17: Same as byte 3-7 for third finger down | ||
344 | * byte 18-22: Same as byte 3-7 for fourth finger down | ||
345 | * byte 23-27: Same as byte 3-7 for fifth finger down | ||
346 | */ | ||
347 | |||
348 | finger_data = data + 2; | ||
349 | for (i = 0; i < ELAN_MAX_FINGERS; i++) { | ||
350 | if (data[1] & BIT(i + 3)) { | ||
351 | elan_report_mt_slot(drvdata, finger_data, i); | ||
352 | finger_data += ELAN_FINGER_DATA_LEN; | ||
353 | } else { | ||
354 | elan_report_mt_slot(drvdata, NULL, i); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | input_report_key(input, BTN_LEFT, data[1] & 0x01); | ||
359 | input_mt_sync_frame(input); | ||
360 | input_sync(input); | ||
361 | } | ||
362 | |||
232 | static int elan_raw_event(struct hid_device *hdev, | 363 | static int elan_raw_event(struct hid_device *hdev, |
233 | struct hid_report *report, u8 *data, int size) | 364 | struct hid_report *report, u8 *data, int size) |
234 | { | 365 | { |
@@ -241,11 +372,16 @@ static int elan_raw_event(struct hid_device *hdev, | |||
241 | data[0] == ELAN_MT_FIRST_FINGER || | 372 | data[0] == ELAN_MT_FIRST_FINGER || |
242 | data[0] == ELAN_MT_SECOND_FINGER) { | 373 | data[0] == ELAN_MT_SECOND_FINGER) { |
243 | if (size == ELAN_INPUT_REPORT_SIZE) { | 374 | if (size == ELAN_INPUT_REPORT_SIZE) { |
244 | elan_report_input(drvdata, data); | 375 | elan_usb_report_input(drvdata, data); |
245 | return 1; | 376 | return 1; |
246 | } | 377 | } |
247 | } | 378 | } |
248 | 379 | ||
380 | if (data[0] == ELAN_MT_I2C && size == ELAN_I2C_REPORT_SIZE) { | ||
381 | elan_i2c_report_input(drvdata, data); | ||
382 | return 1; | ||
383 | } | ||
384 | |||
249 | return 0; | 385 | return 0; |
250 | } | 386 | } |
251 | 387 | ||
@@ -343,7 +479,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
343 | if (!drvdata) | 479 | if (!drvdata) |
344 | return -ENOMEM; | 480 | return -ENOMEM; |
345 | 481 | ||
346 | drvdata->settings = (struct elan_touchpad_settings *)id->driver_data; | ||
347 | hid_set_drvdata(hdev, drvdata); | 482 | hid_set_drvdata(hdev, drvdata); |
348 | 483 | ||
349 | ret = hid_parse(hdev); | 484 | ret = hid_parse(hdev); |
@@ -371,9 +506,11 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
371 | if (ret) | 506 | if (ret) |
372 | goto err; | 507 | goto err; |
373 | 508 | ||
374 | ret = elan_init_mute_led(hdev); | 509 | if (id->driver_data & ELAN_HAS_LED) { |
375 | if (ret) | 510 | ret = elan_init_mute_led(hdev); |
376 | goto err; | 511 | if (ret) |
512 | goto err; | ||
513 | } | ||
377 | 514 | ||
378 | return 0; | 515 | return 0; |
379 | err: | 516 | err: |
@@ -386,22 +523,14 @@ static void elan_remove(struct hid_device *hdev) | |||
386 | hid_hw_stop(hdev); | 523 | hid_hw_stop(hdev); |
387 | } | 524 | } |
388 | 525 | ||
389 | static 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 | |||
399 | static const struct hid_device_id elan_devices[] = { | 526 | static const struct hid_device_id elan_devices[] = { |
527 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2), | ||
528 | .driver_data = ELAN_HAS_LED }, | ||
400 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER), | 529 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER), |
401 | (kernel_ulong_t)&hp_x2_10_touchpad_data}, | 530 | .driver_data = ELAN_HAS_LED }, |
531 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) }, | ||
402 | { } | 532 | { } |
403 | }; | 533 | }; |
404 | |||
405 | MODULE_DEVICE_TABLE(hid, elan_devices); | 534 | MODULE_DEVICE_TABLE(hid, elan_devices); |
406 | 535 | ||
407 | static struct hid_driver elan_driver = { | 536 | static struct hid_driver elan_driver = { |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a1ee8f643f24..79bdf0c7e351 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -369,6 +369,8 @@ | |||
369 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 | 369 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 |
370 | 370 | ||
371 | #define USB_VENDOR_ID_ELAN 0x04f3 | 371 | #define USB_VENDOR_ID_ELAN 0x04f3 |
372 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 | ||
373 | #define USB_DEVICE_ID_HP_X2 0x074d | ||
372 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 | 374 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 |
373 | 375 | ||
374 | #define USB_VENDOR_ID_ELECOM 0x056e | 376 | #define USB_VENDOR_ID_ELECOM 0x056e |