1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * USB Wacom tablet support - Wacom specific code |
4 | */ |
5 | |
6 | #include "wacom_wac.h" |
7 | #include "wacom.h" |
8 | #include <linux/input/mt.h> |
9 | #include <linux/jiffies.h> |
10 | |
11 | /* resolution for penabled devices */ |
12 | #define WACOM_PL_RES 20 |
13 | #define WACOM_PENPRTN_RES 40 |
14 | #define WACOM_VOLITO_RES 50 |
15 | #define WACOM_GRAPHIRE_RES 80 |
16 | #define WACOM_INTUOS_RES 100 |
17 | #define WACOM_INTUOS3_RES 200 |
18 | |
19 | /* Newer Cintiq and DTU have an offset between tablet and screen areas */ |
20 | #define WACOM_DTU_OFFSET 200 |
21 | #define WACOM_CINTIQ_OFFSET 400 |
22 | |
23 | /* |
24 | * Scale factor relating reported contact size to logical contact area. |
25 | * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo |
26 | */ |
27 | #define WACOM_CONTACT_AREA_SCALE 2607 |
28 | |
29 | static bool touch_arbitration = 1; |
30 | module_param(touch_arbitration, bool, 0644); |
31 | MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)" ); |
32 | |
33 | static void wacom_report_numbered_buttons(struct input_dev *input_dev, |
34 | int button_count, int mask); |
35 | |
36 | static int wacom_numbered_button_to_key(int n); |
37 | |
38 | static void wacom_update_led(struct wacom *wacom, int button_count, int mask, |
39 | int group); |
40 | |
41 | static void wacom_force_proxout(struct wacom_wac *wacom_wac) |
42 | { |
43 | struct input_dev *input = wacom_wac->pen_input; |
44 | |
45 | wacom_wac->shared->stylus_in_proximity = 0; |
46 | |
47 | input_report_key(dev: input, BTN_TOUCH, value: 0); |
48 | input_report_key(dev: input, BTN_STYLUS, value: 0); |
49 | input_report_key(dev: input, BTN_STYLUS2, value: 0); |
50 | input_report_key(dev: input, BTN_STYLUS3, value: 0); |
51 | input_report_key(dev: input, code: wacom_wac->tool[0], value: 0); |
52 | if (wacom_wac->serial[0]) { |
53 | input_report_abs(dev: input, ABS_MISC, value: 0); |
54 | } |
55 | input_report_abs(dev: input, ABS_PRESSURE, value: 0); |
56 | |
57 | wacom_wac->tool[0] = 0; |
58 | wacom_wac->id[0] = 0; |
59 | wacom_wac->serial[0] = 0; |
60 | |
61 | input_sync(dev: input); |
62 | } |
63 | |
64 | void wacom_idleprox_timeout(struct timer_list *list) |
65 | { |
66 | struct wacom *wacom = from_timer(wacom, list, idleprox_timer); |
67 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
68 | |
69 | if (!wacom_wac->hid_data.sense_state) { |
70 | return; |
71 | } |
72 | |
73 | hid_warn(wacom->hdev, "%s: tool appears to be hung in-prox. forcing it out.\n" , __func__); |
74 | wacom_force_proxout(wacom_wac); |
75 | } |
76 | |
77 | /* |
78 | * Percent of battery capacity for Graphire. |
79 | * 8th value means AC online and show 100% capacity. |
80 | */ |
81 | static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 }; |
82 | |
83 | /* |
84 | * Percent of battery capacity for Intuos4 WL, AC has a separate bit. |
85 | */ |
86 | static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 }; |
87 | |
88 | static void __wacom_notify_battery(struct wacom_battery *battery, |
89 | int bat_status, int bat_capacity, |
90 | bool bat_charging, bool bat_connected, |
91 | bool ps_connected) |
92 | { |
93 | bool changed = battery->bat_status != bat_status || |
94 | battery->battery_capacity != bat_capacity || |
95 | battery->bat_charging != bat_charging || |
96 | battery->bat_connected != bat_connected || |
97 | battery->ps_connected != ps_connected; |
98 | |
99 | if (changed) { |
100 | battery->bat_status = bat_status; |
101 | battery->battery_capacity = bat_capacity; |
102 | battery->bat_charging = bat_charging; |
103 | battery->bat_connected = bat_connected; |
104 | battery->ps_connected = ps_connected; |
105 | |
106 | if (battery->battery) |
107 | power_supply_changed(psy: battery->battery); |
108 | } |
109 | } |
110 | |
111 | static void wacom_notify_battery(struct wacom_wac *wacom_wac, |
112 | int bat_status, int bat_capacity, bool bat_charging, |
113 | bool bat_connected, bool ps_connected) |
114 | { |
115 | struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); |
116 | bool bat_initialized = wacom->battery.battery; |
117 | bool has_quirk = wacom_wac->features.quirks & WACOM_QUIRK_BATTERY; |
118 | |
119 | if (bat_initialized != has_quirk) |
120 | wacom_schedule_work(wacom_wac, which: WACOM_WORKER_BATTERY); |
121 | |
122 | __wacom_notify_battery(battery: &wacom->battery, bat_status, bat_capacity, |
123 | bat_charging, bat_connected, ps_connected); |
124 | } |
125 | |
126 | static int wacom_penpartner_irq(struct wacom_wac *wacom) |
127 | { |
128 | unsigned char *data = wacom->data; |
129 | struct input_dev *input = wacom->pen_input; |
130 | |
131 | switch (data[0]) { |
132 | case 1: |
133 | if (data[5] & 0x80) { |
134 | wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
135 | wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; |
136 | input_report_key(dev: input, code: wacom->tool[0], value: 1); |
137 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); /* report tool id */ |
138 | input_report_abs(dev: input, ABS_X, value: get_unaligned_le16(p: &data[1])); |
139 | input_report_abs(dev: input, ABS_Y, value: get_unaligned_le16(p: &data[3])); |
140 | input_report_abs(dev: input, ABS_PRESSURE, value: (signed char)data[6] + 127); |
141 | input_report_key(dev: input, BTN_TOUCH, value: ((signed char)data[6] > -127)); |
142 | input_report_key(dev: input, BTN_STYLUS, value: (data[5] & 0x40)); |
143 | } else { |
144 | input_report_key(dev: input, code: wacom->tool[0], value: 0); |
145 | input_report_abs(dev: input, ABS_MISC, value: 0); /* report tool id */ |
146 | input_report_abs(dev: input, ABS_PRESSURE, value: -1); |
147 | input_report_key(dev: input, BTN_TOUCH, value: 0); |
148 | } |
149 | break; |
150 | |
151 | case 2: |
152 | input_report_key(dev: input, BTN_TOOL_PEN, value: 1); |
153 | input_report_abs(dev: input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ |
154 | input_report_abs(dev: input, ABS_X, value: get_unaligned_le16(p: &data[1])); |
155 | input_report_abs(dev: input, ABS_Y, value: get_unaligned_le16(p: &data[3])); |
156 | input_report_abs(dev: input, ABS_PRESSURE, value: (signed char)data[6] + 127); |
157 | input_report_key(dev: input, BTN_TOUCH, value: ((signed char)data[6] > -80) && !(data[5] & 0x20)); |
158 | input_report_key(dev: input, BTN_STYLUS, value: (data[5] & 0x40)); |
159 | break; |
160 | |
161 | default: |
162 | dev_dbg(input->dev.parent, |
163 | "%s: received unknown report #%d\n" , __func__, data[0]); |
164 | return 0; |
165 | } |
166 | |
167 | return 1; |
168 | } |
169 | |
170 | static int wacom_pl_irq(struct wacom_wac *wacom) |
171 | { |
172 | struct wacom_features *features = &wacom->features; |
173 | unsigned char *data = wacom->data; |
174 | struct input_dev *input = wacom->pen_input; |
175 | int prox, pressure; |
176 | |
177 | if (data[0] != WACOM_REPORT_PENABLED) { |
178 | dev_dbg(input->dev.parent, |
179 | "%s: received unknown report #%d\n" , __func__, data[0]); |
180 | return 0; |
181 | } |
182 | |
183 | prox = data[1] & 0x40; |
184 | |
185 | if (!wacom->id[0]) { |
186 | if ((data[0] & 0x10) || (data[4] & 0x20)) { |
187 | wacom->tool[0] = BTN_TOOL_RUBBER; |
188 | wacom->id[0] = ERASER_DEVICE_ID; |
189 | } |
190 | else { |
191 | wacom->tool[0] = BTN_TOOL_PEN; |
192 | wacom->id[0] = STYLUS_DEVICE_ID; |
193 | } |
194 | } |
195 | |
196 | /* If the eraser is in prox, STYLUS2 is always set. If we |
197 | * mis-detected the type and notice that STYLUS2 isn't set |
198 | * then force the eraser out of prox and let the pen in. |
199 | */ |
200 | if (wacom->tool[0] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { |
201 | input_report_key(dev: input, BTN_TOOL_RUBBER, value: 0); |
202 | input_report_abs(dev: input, ABS_MISC, value: 0); |
203 | input_sync(dev: input); |
204 | wacom->tool[0] = BTN_TOOL_PEN; |
205 | wacom->id[0] = STYLUS_DEVICE_ID; |
206 | } |
207 | |
208 | if (prox) { |
209 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
210 | if (features->pressure_max > 255) |
211 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); |
212 | pressure += (features->pressure_max + 1) / 2; |
213 | |
214 | input_report_abs(dev: input, ABS_X, value: data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); |
215 | input_report_abs(dev: input, ABS_Y, value: data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); |
216 | input_report_abs(dev: input, ABS_PRESSURE, value: pressure); |
217 | |
218 | input_report_key(dev: input, BTN_TOUCH, value: data[4] & 0x08); |
219 | input_report_key(dev: input, BTN_STYLUS, value: data[4] & 0x10); |
220 | /* Only allow the stylus2 button to be reported for the pen tool. */ |
221 | input_report_key(dev: input, BTN_STYLUS2, value: (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20)); |
222 | } |
223 | |
224 | if (!prox) |
225 | wacom->id[0] = 0; |
226 | input_report_key(dev: input, code: wacom->tool[0], value: prox); |
227 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); |
228 | return 1; |
229 | } |
230 | |
231 | static int wacom_ptu_irq(struct wacom_wac *wacom) |
232 | { |
233 | unsigned char *data = wacom->data; |
234 | struct input_dev *input = wacom->pen_input; |
235 | |
236 | if (data[0] != WACOM_REPORT_PENABLED) { |
237 | dev_dbg(input->dev.parent, |
238 | "%s: received unknown report #%d\n" , __func__, data[0]); |
239 | return 0; |
240 | } |
241 | |
242 | if (data[1] & 0x04) { |
243 | input_report_key(dev: input, BTN_TOOL_RUBBER, value: data[1] & 0x20); |
244 | input_report_key(dev: input, BTN_TOUCH, value: data[1] & 0x08); |
245 | wacom->id[0] = ERASER_DEVICE_ID; |
246 | } else { |
247 | input_report_key(dev: input, BTN_TOOL_PEN, value: data[1] & 0x20); |
248 | input_report_key(dev: input, BTN_TOUCH, value: data[1] & 0x01); |
249 | wacom->id[0] = STYLUS_DEVICE_ID; |
250 | } |
251 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); /* report tool id */ |
252 | input_report_abs(dev: input, ABS_X, le16_to_cpup(p: (__le16 *)&data[2])); |
253 | input_report_abs(dev: input, ABS_Y, le16_to_cpup(p: (__le16 *)&data[4])); |
254 | input_report_abs(dev: input, ABS_PRESSURE, le16_to_cpup(p: (__le16 *)&data[6])); |
255 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 0x02); |
256 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 0x10); |
257 | return 1; |
258 | } |
259 | |
260 | static int wacom_dtu_irq(struct wacom_wac *wacom) |
261 | { |
262 | unsigned char *data = wacom->data; |
263 | struct input_dev *input = wacom->pen_input; |
264 | int prox = data[1] & 0x20; |
265 | |
266 | dev_dbg(input->dev.parent, |
267 | "%s: received report #%d" , __func__, data[0]); |
268 | |
269 | if (prox) { |
270 | /* Going into proximity select tool */ |
271 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
272 | if (wacom->tool[0] == BTN_TOOL_PEN) |
273 | wacom->id[0] = STYLUS_DEVICE_ID; |
274 | else |
275 | wacom->id[0] = ERASER_DEVICE_ID; |
276 | } |
277 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 0x02); |
278 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 0x10); |
279 | input_report_abs(dev: input, ABS_X, le16_to_cpup(p: (__le16 *)&data[2])); |
280 | input_report_abs(dev: input, ABS_Y, le16_to_cpup(p: (__le16 *)&data[4])); |
281 | input_report_abs(dev: input, ABS_PRESSURE, value: ((data[7] & 0x01) << 8) | data[6]); |
282 | input_report_key(dev: input, BTN_TOUCH, value: data[1] & 0x05); |
283 | if (!prox) /* out-prox */ |
284 | wacom->id[0] = 0; |
285 | input_report_key(dev: input, code: wacom->tool[0], value: prox); |
286 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); |
287 | return 1; |
288 | } |
289 | |
290 | static int wacom_dtus_irq(struct wacom_wac *wacom) |
291 | { |
292 | unsigned char *data = wacom->data; |
293 | struct input_dev *input = wacom->pen_input; |
294 | unsigned short prox, pressure = 0; |
295 | |
296 | if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) { |
297 | dev_dbg(input->dev.parent, |
298 | "%s: received unknown report #%d" , __func__, data[0]); |
299 | return 0; |
300 | } else if (data[0] == WACOM_REPORT_DTUSPAD) { |
301 | input = wacom->pad_input; |
302 | input_report_key(dev: input, BTN_0, value: (data[1] & 0x01)); |
303 | input_report_key(dev: input, BTN_1, value: (data[1] & 0x02)); |
304 | input_report_key(dev: input, BTN_2, value: (data[1] & 0x04)); |
305 | input_report_key(dev: input, BTN_3, value: (data[1] & 0x08)); |
306 | input_report_abs(dev: input, ABS_MISC, |
307 | value: data[1] & 0x0f ? PAD_DEVICE_ID : 0); |
308 | return 1; |
309 | } else { |
310 | prox = data[1] & 0x80; |
311 | if (prox) { |
312 | switch ((data[1] >> 3) & 3) { |
313 | case 1: /* Rubber */ |
314 | wacom->tool[0] = BTN_TOOL_RUBBER; |
315 | wacom->id[0] = ERASER_DEVICE_ID; |
316 | break; |
317 | |
318 | case 2: /* Pen */ |
319 | wacom->tool[0] = BTN_TOOL_PEN; |
320 | wacom->id[0] = STYLUS_DEVICE_ID; |
321 | break; |
322 | } |
323 | } |
324 | |
325 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 0x20); |
326 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 0x40); |
327 | input_report_abs(dev: input, ABS_X, value: get_unaligned_be16(p: &data[3])); |
328 | input_report_abs(dev: input, ABS_Y, value: get_unaligned_be16(p: &data[5])); |
329 | pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff); |
330 | input_report_abs(dev: input, ABS_PRESSURE, value: pressure); |
331 | input_report_key(dev: input, BTN_TOUCH, value: pressure > 10); |
332 | |
333 | if (!prox) /* out-prox */ |
334 | wacom->id[0] = 0; |
335 | input_report_key(dev: input, code: wacom->tool[0], value: prox); |
336 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); |
337 | return 1; |
338 | } |
339 | } |
340 | |
341 | static int wacom_graphire_irq(struct wacom_wac *wacom) |
342 | { |
343 | struct wacom_features *features = &wacom->features; |
344 | unsigned char *data = wacom->data; |
345 | struct input_dev *input = wacom->pen_input; |
346 | struct input_dev *pad_input = wacom->pad_input; |
347 | int battery_capacity, ps_connected; |
348 | int prox; |
349 | int rw = 0; |
350 | int retval = 0; |
351 | |
352 | if (features->type == GRAPHIRE_BT) { |
353 | if (data[0] != WACOM_REPORT_PENABLED_BT) { |
354 | dev_dbg(input->dev.parent, |
355 | "%s: received unknown report #%d\n" , __func__, |
356 | data[0]); |
357 | goto exit; |
358 | } |
359 | } else if (data[0] != WACOM_REPORT_PENABLED) { |
360 | dev_dbg(input->dev.parent, |
361 | "%s: received unknown report #%d\n" , __func__, data[0]); |
362 | goto exit; |
363 | } |
364 | |
365 | prox = data[1] & 0x80; |
366 | if (prox || wacom->id[0]) { |
367 | if (prox) { |
368 | switch ((data[1] >> 5) & 3) { |
369 | |
370 | case 0: /* Pen */ |
371 | wacom->tool[0] = BTN_TOOL_PEN; |
372 | wacom->id[0] = STYLUS_DEVICE_ID; |
373 | break; |
374 | |
375 | case 1: /* Rubber */ |
376 | wacom->tool[0] = BTN_TOOL_RUBBER; |
377 | wacom->id[0] = ERASER_DEVICE_ID; |
378 | break; |
379 | |
380 | case 2: /* Mouse with wheel */ |
381 | input_report_key(dev: input, BTN_MIDDLE, value: data[1] & 0x04); |
382 | fallthrough; |
383 | |
384 | case 3: /* Mouse without wheel */ |
385 | wacom->tool[0] = BTN_TOOL_MOUSE; |
386 | wacom->id[0] = CURSOR_DEVICE_ID; |
387 | break; |
388 | } |
389 | } |
390 | input_report_abs(dev: input, ABS_X, le16_to_cpup(p: (__le16 *)&data[2])); |
391 | input_report_abs(dev: input, ABS_Y, le16_to_cpup(p: (__le16 *)&data[4])); |
392 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { |
393 | if (features->type == GRAPHIRE_BT) |
394 | input_report_abs(dev: input, ABS_PRESSURE, value: data[6] | |
395 | (((__u16) (data[1] & 0x08)) << 5)); |
396 | else |
397 | input_report_abs(dev: input, ABS_PRESSURE, value: data[6] | |
398 | ((data[7] & 0x03) << 8)); |
399 | input_report_key(dev: input, BTN_TOUCH, value: data[1] & 0x01); |
400 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 0x02); |
401 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 0x04); |
402 | } else { |
403 | input_report_key(dev: input, BTN_LEFT, value: data[1] & 0x01); |
404 | input_report_key(dev: input, BTN_RIGHT, value: data[1] & 0x02); |
405 | if (features->type == WACOM_G4 || |
406 | features->type == WACOM_MO) { |
407 | input_report_abs(dev: input, ABS_DISTANCE, value: data[6] & 0x3f); |
408 | rw = (data[7] & 0x04) - (data[7] & 0x03); |
409 | } else if (features->type == GRAPHIRE_BT) { |
410 | /* Compute distance between mouse and tablet */ |
411 | rw = 44 - (data[6] >> 2); |
412 | rw = clamp_val(rw, 0, 31); |
413 | input_report_abs(dev: input, ABS_DISTANCE, value: rw); |
414 | if (((data[1] >> 5) & 3) == 2) { |
415 | /* Mouse with wheel */ |
416 | input_report_key(dev: input, BTN_MIDDLE, |
417 | value: data[1] & 0x04); |
418 | rw = (data[6] & 0x01) ? -1 : |
419 | (data[6] & 0x02) ? 1 : 0; |
420 | } else { |
421 | rw = 0; |
422 | } |
423 | } else { |
424 | input_report_abs(dev: input, ABS_DISTANCE, value: data[7] & 0x3f); |
425 | rw = -(signed char)data[6]; |
426 | } |
427 | input_report_rel(dev: input, REL_WHEEL, value: rw); |
428 | } |
429 | |
430 | if (!prox) |
431 | wacom->id[0] = 0; |
432 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); /* report tool id */ |
433 | input_report_key(dev: input, code: wacom->tool[0], value: prox); |
434 | input_sync(dev: input); /* sync last event */ |
435 | } |
436 | |
437 | /* send pad data */ |
438 | switch (features->type) { |
439 | case WACOM_G4: |
440 | prox = data[7] & 0xf8; |
441 | if (prox || wacom->id[1]) { |
442 | wacom->id[1] = PAD_DEVICE_ID; |
443 | input_report_key(dev: pad_input, BTN_BACK, value: (data[7] & 0x40)); |
444 | input_report_key(dev: pad_input, BTN_FORWARD, value: (data[7] & 0x80)); |
445 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); |
446 | input_report_rel(dev: pad_input, REL_WHEEL, value: rw); |
447 | if (!prox) |
448 | wacom->id[1] = 0; |
449 | input_report_abs(dev: pad_input, ABS_MISC, value: wacom->id[1]); |
450 | retval = 1; |
451 | } |
452 | break; |
453 | |
454 | case WACOM_MO: |
455 | prox = (data[7] & 0xf8) || data[8]; |
456 | if (prox || wacom->id[1]) { |
457 | wacom->id[1] = PAD_DEVICE_ID; |
458 | input_report_key(dev: pad_input, BTN_BACK, value: (data[7] & 0x08)); |
459 | input_report_key(dev: pad_input, BTN_LEFT, value: (data[7] & 0x20)); |
460 | input_report_key(dev: pad_input, BTN_FORWARD, value: (data[7] & 0x10)); |
461 | input_report_key(dev: pad_input, BTN_RIGHT, value: (data[7] & 0x40)); |
462 | input_report_abs(dev: pad_input, ABS_WHEEL, value: (data[8] & 0x7f)); |
463 | if (!prox) |
464 | wacom->id[1] = 0; |
465 | input_report_abs(dev: pad_input, ABS_MISC, value: wacom->id[1]); |
466 | retval = 1; |
467 | } |
468 | break; |
469 | case GRAPHIRE_BT: |
470 | prox = data[7] & 0x03; |
471 | if (prox || wacom->id[1]) { |
472 | wacom->id[1] = PAD_DEVICE_ID; |
473 | input_report_key(dev: pad_input, BTN_0, value: (data[7] & 0x02)); |
474 | input_report_key(dev: pad_input, BTN_1, value: (data[7] & 0x01)); |
475 | if (!prox) |
476 | wacom->id[1] = 0; |
477 | input_report_abs(dev: pad_input, ABS_MISC, value: wacom->id[1]); |
478 | retval = 1; |
479 | } |
480 | break; |
481 | } |
482 | |
483 | /* Store current battery capacity and power supply state */ |
484 | if (features->type == GRAPHIRE_BT) { |
485 | rw = (data[7] >> 2 & 0x07); |
486 | battery_capacity = batcap_gr[rw]; |
487 | ps_connected = rw == 7; |
488 | wacom_notify_battery(wacom_wac: wacom, WACOM_POWER_SUPPLY_STATUS_AUTO, |
489 | bat_capacity: battery_capacity, bat_charging: ps_connected, bat_connected: 1, |
490 | ps_connected); |
491 | } |
492 | exit: |
493 | return retval; |
494 | } |
495 | |
496 | static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac) |
497 | { |
498 | struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); |
499 | struct wacom_features *features = &wacom_wac->features; |
500 | struct hid_report *r; |
501 | struct hid_report_enum *re; |
502 | |
503 | re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]); |
504 | if (features->type == INTUOSHT2) |
505 | r = re->report_id_hash[WACOM_REPORT_INTUOSHT2_ID]; |
506 | else |
507 | r = re->report_id_hash[WACOM_REPORT_INTUOS_ID1]; |
508 | if (r) { |
509 | hid_hw_request(hdev: wacom->hdev, report: r, reqtype: HID_REQ_GET_REPORT); |
510 | } |
511 | } |
512 | |
513 | static int wacom_intuos_pad(struct wacom_wac *wacom) |
514 | { |
515 | struct wacom_features *features = &wacom->features; |
516 | unsigned char *data = wacom->data; |
517 | struct input_dev *input = wacom->pad_input; |
518 | int i; |
519 | int buttons = 0, nbuttons = features->numbered_buttons; |
520 | int keys = 0, nkeys = 0; |
521 | int ring1 = 0, ring2 = 0; |
522 | int strip1 = 0, strip2 = 0; |
523 | bool prox = false; |
524 | bool wrench = false, keyboard = false, mute_touch = false, = false, |
525 | info = false; |
526 | |
527 | /* pad packets. Works as a second tool and is always in prox */ |
528 | if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD || |
529 | data[0] == WACOM_REPORT_CINTIQPAD)) |
530 | return 0; |
531 | |
532 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
533 | buttons = (data[3] << 1) | (data[2] & 0x01); |
534 | ring1 = data[1]; |
535 | } else if (features->type == DTK) { |
536 | buttons = data[6]; |
537 | } else if (features->type == WACOM_13HD) { |
538 | buttons = (data[4] << 1) | (data[3] & 0x01); |
539 | } else if (features->type == WACOM_24HD) { |
540 | buttons = (data[8] << 8) | data[6]; |
541 | ring1 = data[1]; |
542 | ring2 = data[2]; |
543 | |
544 | /* |
545 | * Three "buttons" are available on the 24HD which are |
546 | * physically implemented as a touchstrip. Each button |
547 | * is approximately 3 bits wide with a 2 bit spacing. |
548 | * The raw touchstrip bits are stored at: |
549 | * ((data[3] & 0x1f) << 8) | data[4]) |
550 | */ |
551 | nkeys = 3; |
552 | keys = ((data[3] & 0x1C) ? 1<<2 : 0) | |
553 | ((data[4] & 0xE0) ? 1<<1 : 0) | |
554 | ((data[4] & 0x07) ? 1<<0 : 0); |
555 | keyboard = !!(data[4] & 0xE0); |
556 | info = !!(data[3] & 0x1C); |
557 | |
558 | if (features->oPid) { |
559 | mute_touch = !!(data[4] & 0x07); |
560 | if (mute_touch) |
561 | wacom->shared->is_touch_on = |
562 | !wacom->shared->is_touch_on; |
563 | } else { |
564 | wrench = !!(data[4] & 0x07); |
565 | } |
566 | } else if (features->type == WACOM_27QHD) { |
567 | nkeys = 3; |
568 | keys = data[2] & 0x07; |
569 | |
570 | wrench = !!(data[2] & 0x01); |
571 | keyboard = !!(data[2] & 0x02); |
572 | |
573 | if (features->oPid) { |
574 | mute_touch = !!(data[2] & 0x04); |
575 | if (mute_touch) |
576 | wacom->shared->is_touch_on = |
577 | !wacom->shared->is_touch_on; |
578 | } else { |
579 | menu = !!(data[2] & 0x04); |
580 | } |
581 | input_report_abs(dev: input, ABS_X, be16_to_cpup(p: (__be16 *)&data[4])); |
582 | input_report_abs(dev: input, ABS_Y, be16_to_cpup(p: (__be16 *)&data[6])); |
583 | input_report_abs(dev: input, ABS_Z, be16_to_cpup(p: (__be16 *)&data[8])); |
584 | } else if (features->type == CINTIQ_HYBRID) { |
585 | /* |
586 | * Do not send hardware buttons under Android. They |
587 | * are already sent to the system through GPIO (and |
588 | * have different meaning). |
589 | * |
590 | * d-pad right -> data[4] & 0x10 |
591 | * d-pad up -> data[4] & 0x20 |
592 | * d-pad left -> data[4] & 0x40 |
593 | * d-pad down -> data[4] & 0x80 |
594 | * d-pad center -> data[3] & 0x01 |
595 | */ |
596 | buttons = (data[4] << 1) | (data[3] & 0x01); |
597 | } else if (features->type == CINTIQ_COMPANION_2) { |
598 | /* d-pad right -> data[2] & 0x10 |
599 | * d-pad up -> data[2] & 0x20 |
600 | * d-pad left -> data[2] & 0x40 |
601 | * d-pad down -> data[2] & 0x80 |
602 | * d-pad center -> data[1] & 0x01 |
603 | */ |
604 | buttons = ((data[2] >> 4) << 7) | |
605 | ((data[1] & 0x04) << 4) | |
606 | ((data[2] & 0x0F) << 2) | |
607 | (data[1] & 0x03); |
608 | } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { |
609 | /* |
610 | * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in |
611 | * addition to the mechanical switch. Switch data is |
612 | * stored in data[4], capacitive data in data[5]. |
613 | * |
614 | * Touch ring mode switch (data[3]) has no capacitive sensor |
615 | */ |
616 | buttons = (data[4] << 1) | (data[3] & 0x01); |
617 | ring1 = data[2]; |
618 | } else { |
619 | if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) { |
620 | buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) | |
621 | (data[6] << 1) | (data[5] & 0x01); |
622 | |
623 | if (features->type == WACOM_22HD) { |
624 | nkeys = 3; |
625 | keys = data[9] & 0x07; |
626 | |
627 | info = !!(data[9] & 0x01); |
628 | wrench = !!(data[9] & 0x02); |
629 | } |
630 | } else { |
631 | buttons = ((data[6] & 0x10) << 5) | |
632 | ((data[5] & 0x10) << 4) | |
633 | ((data[6] & 0x0F) << 4) | |
634 | (data[5] & 0x0F); |
635 | } |
636 | strip1 = ((data[1] & 0x1f) << 8) | data[2]; |
637 | strip2 = ((data[3] & 0x1f) << 8) | data[4]; |
638 | } |
639 | |
640 | prox = (buttons & ~(~0U << nbuttons)) | (keys & ~(~0U << nkeys)) | |
641 | (ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2; |
642 | |
643 | wacom_report_numbered_buttons(input_dev: input, button_count: nbuttons, mask: buttons); |
644 | |
645 | for (i = 0; i < nkeys; i++) |
646 | input_report_key(dev: input, KEY_PROG1 + i, value: keys & (1 << i)); |
647 | |
648 | input_report_key(dev: input, KEY_BUTTONCONFIG, value: wrench); |
649 | input_report_key(dev: input, KEY_ONSCREEN_KEYBOARD, value: keyboard); |
650 | input_report_key(dev: input, KEY_CONTROLPANEL, value: menu); |
651 | input_report_key(dev: input, KEY_INFO, value: info); |
652 | |
653 | if (wacom->shared && wacom->shared->touch_input) { |
654 | input_report_switch(dev: wacom->shared->touch_input, |
655 | SW_MUTE_DEVICE, |
656 | value: !wacom->shared->is_touch_on); |
657 | input_sync(dev: wacom->shared->touch_input); |
658 | } |
659 | |
660 | input_report_abs(dev: input, ABS_RX, value: strip1); |
661 | input_report_abs(dev: input, ABS_RY, value: strip2); |
662 | |
663 | input_report_abs(dev: input, ABS_WHEEL, value: (ring1 & 0x80) ? (ring1 & 0x7f) : 0); |
664 | input_report_abs(dev: input, ABS_THROTTLE, value: (ring2 & 0x80) ? (ring2 & 0x7f) : 0); |
665 | |
666 | input_report_key(dev: input, code: wacom->tool[1], value: prox ? 1 : 0); |
667 | input_report_abs(dev: input, ABS_MISC, value: prox ? PAD_DEVICE_ID : 0); |
668 | |
669 | input_event(dev: input, EV_MSC, MSC_SERIAL, value: 0xffffffff); |
670 | |
671 | return 1; |
672 | } |
673 | |
674 | static int wacom_intuos_id_mangle(int tool_id) |
675 | { |
676 | return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF); |
677 | } |
678 | |
679 | static bool wacom_is_art_pen(int tool_id) |
680 | { |
681 | bool is_art_pen = false; |
682 | |
683 | switch (tool_id) { |
684 | case 0x885: /* Intuos3 Marker Pen */ |
685 | case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ |
686 | case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ |
687 | is_art_pen = true; |
688 | break; |
689 | } |
690 | return is_art_pen; |
691 | } |
692 | |
693 | static int wacom_intuos_get_tool_type(int tool_id) |
694 | { |
695 | int tool_type = BTN_TOOL_PEN; |
696 | |
697 | if (wacom_is_art_pen(tool_id)) |
698 | return tool_type; |
699 | |
700 | switch (tool_id) { |
701 | case 0x812: /* Inking pen */ |
702 | case 0x801: /* Intuos3 Inking pen */ |
703 | case 0x12802: /* Intuos4/5 Inking Pen */ |
704 | case 0x012: |
705 | tool_type = BTN_TOOL_PENCIL; |
706 | break; |
707 | |
708 | case 0x822: /* Pen */ |
709 | case 0x842: |
710 | case 0x852: |
711 | case 0x823: /* Intuos3 Grip Pen */ |
712 | case 0x813: /* Intuos3 Classic Pen */ |
713 | case 0x802: /* Intuos4/5 13HD/24HD General Pen */ |
714 | case 0x8e2: /* IntuosHT2 pen */ |
715 | case 0x022: |
716 | case 0x200: /* Pro Pen 3 */ |
717 | case 0x04200: /* Pro Pen 3 */ |
718 | case 0x10842: /* MobileStudio Pro Pro Pen slim */ |
719 | case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ |
720 | case 0x16802: /* Cintiq 13HD Pro Pen */ |
721 | case 0x18802: /* DTH2242 Pen */ |
722 | case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ |
723 | case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */ |
724 | tool_type = BTN_TOOL_PEN; |
725 | break; |
726 | |
727 | case 0x832: /* Stroke pen */ |
728 | case 0x032: |
729 | tool_type = BTN_TOOL_BRUSH; |
730 | break; |
731 | |
732 | case 0x007: /* Mouse 4D and 2D */ |
733 | case 0x09c: |
734 | case 0x094: |
735 | case 0x017: /* Intuos3 2D Mouse */ |
736 | case 0x806: /* Intuos4 Mouse */ |
737 | tool_type = BTN_TOOL_MOUSE; |
738 | break; |
739 | |
740 | case 0x096: /* Lens cursor */ |
741 | case 0x097: /* Intuos3 Lens cursor */ |
742 | case 0x006: /* Intuos4 Lens cursor */ |
743 | tool_type = BTN_TOOL_LENS; |
744 | break; |
745 | |
746 | case 0x82a: /* Eraser */ |
747 | case 0x84a: |
748 | case 0x85a: |
749 | case 0x91a: |
750 | case 0xd1a: |
751 | case 0x0fa: |
752 | case 0x82b: /* Intuos3 Grip Pen Eraser */ |
753 | case 0x81b: /* Intuos3 Classic Pen Eraser */ |
754 | case 0x91b: /* Intuos3 Airbrush Eraser */ |
755 | case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */ |
756 | case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */ |
757 | case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ |
758 | case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */ |
759 | case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */ |
760 | case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */ |
761 | case 0x1084a: /* MobileStudio Pro Pro Pen slim Eraser */ |
762 | case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */ |
763 | case 0x1880a: /* DTH2242 Eraser */ |
764 | case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */ |
765 | tool_type = BTN_TOOL_RUBBER; |
766 | break; |
767 | |
768 | case 0xd12: |
769 | case 0x912: |
770 | case 0x112: |
771 | case 0x913: /* Intuos3 Airbrush */ |
772 | case 0x902: /* Intuos4/5 13HD/24HD Airbrush */ |
773 | case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */ |
774 | tool_type = BTN_TOOL_AIRBRUSH; |
775 | break; |
776 | } |
777 | return tool_type; |
778 | } |
779 | |
780 | static void wacom_exit_report(struct wacom_wac *wacom) |
781 | { |
782 | struct input_dev *input = wacom->pen_input; |
783 | struct wacom_features *features = &wacom->features; |
784 | unsigned char *data = wacom->data; |
785 | int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; |
786 | |
787 | /* |
788 | * Reset all states otherwise we lose the initial states |
789 | * when in-prox next time |
790 | */ |
791 | input_report_abs(dev: input, ABS_X, value: 0); |
792 | input_report_abs(dev: input, ABS_Y, value: 0); |
793 | input_report_abs(dev: input, ABS_DISTANCE, value: 0); |
794 | input_report_abs(dev: input, ABS_TILT_X, value: 0); |
795 | input_report_abs(dev: input, ABS_TILT_Y, value: 0); |
796 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { |
797 | input_report_key(dev: input, BTN_LEFT, value: 0); |
798 | input_report_key(dev: input, BTN_MIDDLE, value: 0); |
799 | input_report_key(dev: input, BTN_RIGHT, value: 0); |
800 | input_report_key(dev: input, BTN_SIDE, value: 0); |
801 | input_report_key(dev: input, BTN_EXTRA, value: 0); |
802 | input_report_abs(dev: input, ABS_THROTTLE, value: 0); |
803 | input_report_abs(dev: input, ABS_RZ, value: 0); |
804 | } else { |
805 | input_report_abs(dev: input, ABS_PRESSURE, value: 0); |
806 | input_report_key(dev: input, BTN_STYLUS, value: 0); |
807 | input_report_key(dev: input, BTN_STYLUS2, value: 0); |
808 | input_report_key(dev: input, BTN_TOUCH, value: 0); |
809 | input_report_abs(dev: input, ABS_WHEEL, value: 0); |
810 | if (features->type >= INTUOS3S) |
811 | input_report_abs(dev: input, ABS_Z, value: 0); |
812 | } |
813 | input_report_key(dev: input, code: wacom->tool[idx], value: 0); |
814 | input_report_abs(dev: input, ABS_MISC, value: 0); /* reset tool id */ |
815 | input_event(dev: input, EV_MSC, MSC_SERIAL, value: wacom->serial[idx]); |
816 | wacom->id[idx] = 0; |
817 | } |
818 | |
819 | static int wacom_intuos_inout(struct wacom_wac *wacom) |
820 | { |
821 | struct wacom_features *features = &wacom->features; |
822 | unsigned char *data = wacom->data; |
823 | struct input_dev *input = wacom->pen_input; |
824 | int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; |
825 | |
826 | if (!(((data[1] & 0xfc) == 0xc0) || /* in prox */ |
827 | ((data[1] & 0xfe) == 0x20) || /* in range */ |
828 | ((data[1] & 0xfe) == 0x80))) /* out prox */ |
829 | return 0; |
830 | |
831 | /* Enter report */ |
832 | if ((data[1] & 0xfc) == 0xc0) { |
833 | /* serial number of the tool */ |
834 | wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) + |
835 | (data[4] << 20) + (data[5] << 12) + |
836 | (data[6] << 4) + (data[7] >> 4); |
837 | |
838 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) | |
839 | ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8); |
840 | |
841 | wacom->tool[idx] = wacom_intuos_get_tool_type(tool_id: wacom->id[idx]); |
842 | |
843 | wacom->shared->stylus_in_proximity = true; |
844 | return 1; |
845 | } |
846 | |
847 | /* in Range */ |
848 | if ((data[1] & 0xfe) == 0x20) { |
849 | if (features->type != INTUOSHT2) |
850 | wacom->shared->stylus_in_proximity = true; |
851 | |
852 | /* in Range while exiting */ |
853 | if (wacom->reporting_data) { |
854 | input_report_key(dev: input, BTN_TOUCH, value: 0); |
855 | input_report_abs(dev: input, ABS_PRESSURE, value: 0); |
856 | input_report_abs(dev: input, ABS_DISTANCE, value: wacom->features.distance_max); |
857 | return 2; |
858 | } |
859 | return 1; |
860 | } |
861 | |
862 | /* Exit report */ |
863 | if ((data[1] & 0xfe) == 0x80) { |
864 | wacom->shared->stylus_in_proximity = false; |
865 | wacom->reporting_data = false; |
866 | |
867 | /* don't report exit if we don't know the ID */ |
868 | if (!wacom->id[idx]) |
869 | return 1; |
870 | |
871 | wacom_exit_report(wacom); |
872 | return 2; |
873 | } |
874 | |
875 | return 0; |
876 | } |
877 | |
878 | static inline bool touch_is_muted(struct wacom_wac *wacom_wac) |
879 | { |
880 | return wacom_wac->probe_complete && |
881 | wacom_wac->shared->has_mute_touch_switch && |
882 | !wacom_wac->shared->is_touch_on; |
883 | } |
884 | |
885 | static inline bool report_touch_events(struct wacom_wac *wacom) |
886 | { |
887 | return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1); |
888 | } |
889 | |
890 | static inline bool delay_pen_events(struct wacom_wac *wacom) |
891 | { |
892 | return (wacom->shared->touch_down && touch_arbitration); |
893 | } |
894 | |
895 | static int wacom_intuos_general(struct wacom_wac *wacom) |
896 | { |
897 | struct wacom_features *features = &wacom->features; |
898 | unsigned char *data = wacom->data; |
899 | struct input_dev *input = wacom->pen_input; |
900 | int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; |
901 | unsigned char type = (data[1] >> 1) & 0x0F; |
902 | unsigned int x, y, distance, t; |
903 | |
904 | if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_CINTIQ && |
905 | data[0] != WACOM_REPORT_INTUOS_PEN) |
906 | return 0; |
907 | |
908 | if (delay_pen_events(wacom)) |
909 | return 1; |
910 | |
911 | /* don't report events if we don't know the tool ID */ |
912 | if (!wacom->id[idx]) { |
913 | /* but reschedule a read of the current tool */ |
914 | wacom_intuos_schedule_prox_event(wacom_wac: wacom); |
915 | return 1; |
916 | } |
917 | |
918 | /* |
919 | * don't report events for invalid data |
920 | */ |
921 | /* older I4 styli don't work with new Cintiqs */ |
922 | if ((!((wacom->id[idx] >> 16) & 0x01) && |
923 | (features->type == WACOM_21UX2)) || |
924 | /* Only large Intuos support Lense Cursor */ |
925 | (wacom->tool[idx] == BTN_TOOL_LENS && |
926 | (features->type == INTUOS3 || |
927 | features->type == INTUOS3S || |
928 | features->type == INTUOS4 || |
929 | features->type == INTUOS4S || |
930 | features->type == INTUOS5 || |
931 | features->type == INTUOS5S || |
932 | features->type == INTUOSPM || |
933 | features->type == INTUOSPS)) || |
934 | /* Cintiq doesn't send data when RDY bit isn't set */ |
935 | (features->type == CINTIQ && !(data[1] & 0x40))) |
936 | return 1; |
937 | |
938 | x = (be16_to_cpup(p: (__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); |
939 | y = (be16_to_cpup(p: (__be16 *)&data[4]) << 1) | (data[9] & 1); |
940 | distance = data[9] >> 2; |
941 | if (features->type < INTUOS3S) { |
942 | x >>= 1; |
943 | y >>= 1; |
944 | distance >>= 1; |
945 | } |
946 | if (features->type == INTUOSHT2) |
947 | distance = features->distance_max - distance; |
948 | input_report_abs(dev: input, ABS_X, value: x); |
949 | input_report_abs(dev: input, ABS_Y, value: y); |
950 | input_report_abs(dev: input, ABS_DISTANCE, value: distance); |
951 | |
952 | switch (type) { |
953 | case 0x00: |
954 | case 0x01: |
955 | case 0x02: |
956 | case 0x03: |
957 | /* general pen packet */ |
958 | t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1); |
959 | if (features->pressure_max < 2047) |
960 | t >>= 1; |
961 | input_report_abs(dev: input, ABS_PRESSURE, value: t); |
962 | if (features->type != INTUOSHT2) { |
963 | input_report_abs(dev: input, ABS_TILT_X, |
964 | value: (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
965 | input_report_abs(dev: input, ABS_TILT_Y, value: (data[8] & 0x7f) - 64); |
966 | } |
967 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 2); |
968 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 4); |
969 | input_report_key(dev: input, BTN_TOUCH, value: t > 10); |
970 | break; |
971 | |
972 | case 0x0a: |
973 | /* airbrush second packet */ |
974 | input_report_abs(dev: input, ABS_WHEEL, |
975 | value: (data[6] << 2) | ((data[7] >> 6) & 3)); |
976 | input_report_abs(dev: input, ABS_TILT_X, |
977 | value: (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
978 | input_report_abs(dev: input, ABS_TILT_Y, value: (data[8] & 0x7f) - 64); |
979 | break; |
980 | |
981 | case 0x05: |
982 | /* Rotation packet */ |
983 | if (features->type >= INTUOS3S) { |
984 | /* I3 marker pen rotation */ |
985 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
986 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : |
987 | ((t-1) / 2 + 450)) : (450 - t / 2) ; |
988 | input_report_abs(dev: input, ABS_Z, value: t); |
989 | } else { |
990 | /* 4D mouse 2nd packet */ |
991 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
992 | input_report_abs(dev: input, ABS_RZ, value: (data[7] & 0x20) ? |
993 | ((t - 1) / 2) : -t / 2); |
994 | } |
995 | break; |
996 | |
997 | case 0x04: |
998 | /* 4D mouse 1st packet */ |
999 | input_report_key(dev: input, BTN_LEFT, value: data[8] & 0x01); |
1000 | input_report_key(dev: input, BTN_MIDDLE, value: data[8] & 0x02); |
1001 | input_report_key(dev: input, BTN_RIGHT, value: data[8] & 0x04); |
1002 | |
1003 | input_report_key(dev: input, BTN_SIDE, value: data[8] & 0x20); |
1004 | input_report_key(dev: input, BTN_EXTRA, value: data[8] & 0x10); |
1005 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
1006 | input_report_abs(dev: input, ABS_THROTTLE, value: (data[8] & 0x08) ? -t : t); |
1007 | break; |
1008 | |
1009 | case 0x06: |
1010 | /* I4 mouse */ |
1011 | input_report_key(dev: input, BTN_LEFT, value: data[6] & 0x01); |
1012 | input_report_key(dev: input, BTN_MIDDLE, value: data[6] & 0x02); |
1013 | input_report_key(dev: input, BTN_RIGHT, value: data[6] & 0x04); |
1014 | input_report_rel(dev: input, REL_WHEEL, value: ((data[7] & 0x80) >> 7) |
1015 | - ((data[7] & 0x40) >> 6)); |
1016 | input_report_key(dev: input, BTN_SIDE, value: data[6] & 0x08); |
1017 | input_report_key(dev: input, BTN_EXTRA, value: data[6] & 0x10); |
1018 | |
1019 | input_report_abs(dev: input, ABS_TILT_X, |
1020 | value: (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
1021 | input_report_abs(dev: input, ABS_TILT_Y, value: (data[8] & 0x7f) - 64); |
1022 | break; |
1023 | |
1024 | case 0x08: |
1025 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
1026 | /* 2D mouse packet */ |
1027 | input_report_key(dev: input, BTN_LEFT, value: data[8] & 0x04); |
1028 | input_report_key(dev: input, BTN_MIDDLE, value: data[8] & 0x08); |
1029 | input_report_key(dev: input, BTN_RIGHT, value: data[8] & 0x10); |
1030 | input_report_rel(dev: input, REL_WHEEL, value: (data[8] & 0x01) |
1031 | - ((data[8] & 0x02) >> 1)); |
1032 | |
1033 | /* I3 2D mouse side buttons */ |
1034 | if (features->type >= INTUOS3S && features->type <= INTUOS3L) { |
1035 | input_report_key(dev: input, BTN_SIDE, value: data[8] & 0x40); |
1036 | input_report_key(dev: input, BTN_EXTRA, value: data[8] & 0x20); |
1037 | } |
1038 | } |
1039 | else if (wacom->tool[idx] == BTN_TOOL_LENS) { |
1040 | /* Lens cursor packets */ |
1041 | input_report_key(dev: input, BTN_LEFT, value: data[8] & 0x01); |
1042 | input_report_key(dev: input, BTN_MIDDLE, value: data[8] & 0x02); |
1043 | input_report_key(dev: input, BTN_RIGHT, value: data[8] & 0x04); |
1044 | input_report_key(dev: input, BTN_SIDE, value: data[8] & 0x10); |
1045 | input_report_key(dev: input, BTN_EXTRA, value: data[8] & 0x08); |
1046 | } |
1047 | break; |
1048 | |
1049 | case 0x07: |
1050 | case 0x09: |
1051 | case 0x0b: |
1052 | case 0x0c: |
1053 | case 0x0d: |
1054 | case 0x0e: |
1055 | case 0x0f: |
1056 | /* unhandled */ |
1057 | break; |
1058 | } |
1059 | |
1060 | input_report_abs(dev: input, ABS_MISC, |
1061 | value: wacom_intuos_id_mangle(tool_id: wacom->id[idx])); /* report tool id */ |
1062 | input_report_key(dev: input, code: wacom->tool[idx], value: 1); |
1063 | input_event(dev: input, EV_MSC, MSC_SERIAL, value: wacom->serial[idx]); |
1064 | wacom->reporting_data = true; |
1065 | return 2; |
1066 | } |
1067 | |
1068 | static int wacom_intuos_irq(struct wacom_wac *wacom) |
1069 | { |
1070 | unsigned char *data = wacom->data; |
1071 | struct input_dev *input = wacom->pen_input; |
1072 | int result; |
1073 | |
1074 | if (data[0] != WACOM_REPORT_PENABLED && |
1075 | data[0] != WACOM_REPORT_INTUOS_ID1 && |
1076 | data[0] != WACOM_REPORT_INTUOS_ID2 && |
1077 | data[0] != WACOM_REPORT_INTUOSPAD && |
1078 | data[0] != WACOM_REPORT_INTUOS_PEN && |
1079 | data[0] != WACOM_REPORT_CINTIQ && |
1080 | data[0] != WACOM_REPORT_CINTIQPAD && |
1081 | data[0] != WACOM_REPORT_INTUOS5PAD) { |
1082 | dev_dbg(input->dev.parent, |
1083 | "%s: received unknown report #%d\n" , __func__, data[0]); |
1084 | return 0; |
1085 | } |
1086 | |
1087 | /* process pad events */ |
1088 | result = wacom_intuos_pad(wacom); |
1089 | if (result) |
1090 | return result; |
1091 | |
1092 | /* process in/out prox events */ |
1093 | result = wacom_intuos_inout(wacom); |
1094 | if (result) |
1095 | return result - 1; |
1096 | |
1097 | /* process general packets */ |
1098 | result = wacom_intuos_general(wacom); |
1099 | if (result) |
1100 | return result - 1; |
1101 | |
1102 | return 0; |
1103 | } |
1104 | |
1105 | static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) |
1106 | { |
1107 | unsigned char *data = wacom_wac->data; |
1108 | struct input_dev *input; |
1109 | struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); |
1110 | struct wacom_remote *remote = wacom->remote; |
1111 | int bat_charging, bat_percent, touch_ring_mode; |
1112 | __u32 serial; |
1113 | int i, index = -1; |
1114 | unsigned long flags; |
1115 | |
1116 | if (data[0] != WACOM_REPORT_REMOTE) { |
1117 | hid_dbg(wacom->hdev, "%s: received unknown report #%d" , |
1118 | __func__, data[0]); |
1119 | return 0; |
1120 | } |
1121 | |
1122 | serial = data[3] + (data[4] << 8) + (data[5] << 16); |
1123 | wacom_wac->id[0] = PAD_DEVICE_ID; |
1124 | |
1125 | spin_lock_irqsave(&remote->remote_lock, flags); |
1126 | |
1127 | for (i = 0; i < WACOM_MAX_REMOTES; i++) { |
1128 | if (remote->remotes[i].serial == serial) { |
1129 | index = i; |
1130 | break; |
1131 | } |
1132 | } |
1133 | |
1134 | if (index < 0 || !remote->remotes[index].registered) |
1135 | goto out; |
1136 | |
1137 | remote->remotes[i].active_time = ktime_get(); |
1138 | input = remote->remotes[index].input; |
1139 | |
1140 | input_report_key(dev: input, BTN_0, value: (data[9] & 0x01)); |
1141 | input_report_key(dev: input, BTN_1, value: (data[9] & 0x02)); |
1142 | input_report_key(dev: input, BTN_2, value: (data[9] & 0x04)); |
1143 | input_report_key(dev: input, BTN_3, value: (data[9] & 0x08)); |
1144 | input_report_key(dev: input, BTN_4, value: (data[9] & 0x10)); |
1145 | input_report_key(dev: input, BTN_5, value: (data[9] & 0x20)); |
1146 | input_report_key(dev: input, BTN_6, value: (data[9] & 0x40)); |
1147 | input_report_key(dev: input, BTN_7, value: (data[9] & 0x80)); |
1148 | |
1149 | input_report_key(dev: input, BTN_8, value: (data[10] & 0x01)); |
1150 | input_report_key(dev: input, BTN_9, value: (data[10] & 0x02)); |
1151 | input_report_key(dev: input, BTN_A, value: (data[10] & 0x04)); |
1152 | input_report_key(dev: input, BTN_B, value: (data[10] & 0x08)); |
1153 | input_report_key(dev: input, BTN_C, value: (data[10] & 0x10)); |
1154 | input_report_key(dev: input, BTN_X, value: (data[10] & 0x20)); |
1155 | input_report_key(dev: input, BTN_Y, value: (data[10] & 0x40)); |
1156 | input_report_key(dev: input, BTN_Z, value: (data[10] & 0x80)); |
1157 | |
1158 | input_report_key(dev: input, BTN_BASE, value: (data[11] & 0x01)); |
1159 | input_report_key(dev: input, BTN_BASE2, value: (data[11] & 0x02)); |
1160 | |
1161 | if (data[12] & 0x80) |
1162 | input_report_abs(dev: input, ABS_WHEEL, value: (data[12] & 0x7f) - 1); |
1163 | else |
1164 | input_report_abs(dev: input, ABS_WHEEL, value: 0); |
1165 | |
1166 | bat_percent = data[7] & 0x7f; |
1167 | bat_charging = !!(data[7] & 0x80); |
1168 | |
1169 | if (data[9] | data[10] | (data[11] & 0x03) | data[12]) |
1170 | input_report_abs(dev: input, ABS_MISC, PAD_DEVICE_ID); |
1171 | else |
1172 | input_report_abs(dev: input, ABS_MISC, value: 0); |
1173 | |
1174 | input_event(dev: input, EV_MSC, MSC_SERIAL, value: serial); |
1175 | |
1176 | input_sync(dev: input); |
1177 | |
1178 | /*Which mode select (LED light) is currently on?*/ |
1179 | touch_ring_mode = (data[11] & 0xC0) >> 6; |
1180 | |
1181 | for (i = 0; i < WACOM_MAX_REMOTES; i++) { |
1182 | if (remote->remotes[i].serial == serial) |
1183 | wacom->led.groups[i].select = touch_ring_mode; |
1184 | } |
1185 | |
1186 | __wacom_notify_battery(battery: &remote->remotes[index].battery, |
1187 | WACOM_POWER_SUPPLY_STATUS_AUTO, bat_capacity: bat_percent, |
1188 | bat_charging, bat_connected: 1, ps_connected: bat_charging); |
1189 | |
1190 | out: |
1191 | spin_unlock_irqrestore(lock: &remote->remote_lock, flags); |
1192 | return 0; |
1193 | } |
1194 | |
1195 | static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) |
1196 | { |
1197 | struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); |
1198 | unsigned char *data = wacom_wac->data; |
1199 | struct wacom_remote *remote = wacom->remote; |
1200 | struct wacom_remote_work_data remote_data; |
1201 | unsigned long flags; |
1202 | int i, ret; |
1203 | |
1204 | if (data[0] != WACOM_REPORT_DEVICE_LIST) |
1205 | return; |
1206 | |
1207 | memset(&remote_data, 0, sizeof(struct wacom_remote_work_data)); |
1208 | |
1209 | for (i = 0; i < WACOM_MAX_REMOTES; i++) { |
1210 | int j = i * 6; |
1211 | int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; |
1212 | |
1213 | remote_data.remote[i].serial = serial; |
1214 | } |
1215 | |
1216 | spin_lock_irqsave(&remote->remote_lock, flags); |
1217 | |
1218 | ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); |
1219 | if (ret != sizeof(remote_data)) { |
1220 | spin_unlock_irqrestore(lock: &remote->remote_lock, flags); |
1221 | hid_err(wacom->hdev, "Can't queue Remote status event.\n" ); |
1222 | return; |
1223 | } |
1224 | |
1225 | spin_unlock_irqrestore(lock: &remote->remote_lock, flags); |
1226 | |
1227 | wacom_schedule_work(wacom_wac, which: WACOM_WORKER_REMOTE); |
1228 | } |
1229 | |
1230 | static int int_dist(int x1, int y1, int x2, int y2) |
1231 | { |
1232 | int x = x2 - x1; |
1233 | int y = y2 - y1; |
1234 | |
1235 | return int_sqrt(x*x + y*y); |
1236 | } |
1237 | |
1238 | static void wacom_intuos_bt_process_data(struct wacom_wac *wacom, |
1239 | unsigned char *data) |
1240 | { |
1241 | memcpy(wacom->data, data, 10); |
1242 | wacom_intuos_irq(wacom); |
1243 | |
1244 | input_sync(dev: wacom->pen_input); |
1245 | if (wacom->pad_input) |
1246 | input_sync(dev: wacom->pad_input); |
1247 | } |
1248 | |
1249 | static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) |
1250 | { |
1251 | unsigned char data[WACOM_PKGLEN_MAX]; |
1252 | int i = 1; |
1253 | unsigned power_raw, battery_capacity, bat_charging, ps_connected; |
1254 | |
1255 | memcpy(data, wacom->data, len); |
1256 | |
1257 | switch (data[0]) { |
1258 | case 0x04: |
1259 | wacom_intuos_bt_process_data(wacom, data: data + i); |
1260 | i += 10; |
1261 | fallthrough; |
1262 | case 0x03: |
1263 | wacom_intuos_bt_process_data(wacom, data: data + i); |
1264 | i += 10; |
1265 | wacom_intuos_bt_process_data(wacom, data: data + i); |
1266 | i += 10; |
1267 | power_raw = data[i]; |
1268 | bat_charging = (power_raw & 0x08) ? 1 : 0; |
1269 | ps_connected = (power_raw & 0x10) ? 1 : 0; |
1270 | battery_capacity = batcap_i4[power_raw & 0x07]; |
1271 | wacom_notify_battery(wacom_wac: wacom, WACOM_POWER_SUPPLY_STATUS_AUTO, |
1272 | bat_capacity: battery_capacity, bat_charging, |
1273 | bat_connected: battery_capacity || bat_charging, |
1274 | ps_connected); |
1275 | break; |
1276 | default: |
1277 | dev_dbg(wacom->pen_input->dev.parent, |
1278 | "Unknown report: %d,%d size:%zu\n" , |
1279 | data[0], data[1], len); |
1280 | return 0; |
1281 | } |
1282 | return 0; |
1283 | } |
1284 | |
1285 | static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) |
1286 | { |
1287 | struct input_dev *input = wacom->touch_input; |
1288 | unsigned touch_max = wacom->features.touch_max; |
1289 | int count = 0; |
1290 | int i; |
1291 | |
1292 | if (!touch_max) |
1293 | return 0; |
1294 | |
1295 | if (touch_max == 1) |
1296 | return test_bit(BTN_TOUCH, input->key) && |
1297 | report_touch_events(wacom); |
1298 | |
1299 | for (i = 0; i < input->mt->num_slots; i++) { |
1300 | struct input_mt_slot *ps = &input->mt->slots[i]; |
1301 | int id = input_mt_get_value(slot: ps, ABS_MT_TRACKING_ID); |
1302 | if (id >= 0) |
1303 | count++; |
1304 | } |
1305 | |
1306 | return count; |
1307 | } |
1308 | |
1309 | static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) |
1310 | { |
1311 | int pen_frame_len, pen_frames; |
1312 | |
1313 | struct input_dev *pen_input = wacom->pen_input; |
1314 | unsigned char *data = wacom->data; |
1315 | int number_of_valid_frames = 0; |
1316 | ktime_t time_interval = 15000000; |
1317 | ktime_t time_packet_received = ktime_get(); |
1318 | int i; |
1319 | |
1320 | if (wacom->features.type == INTUOSP2_BT || |
1321 | wacom->features.type == INTUOSP2S_BT) { |
1322 | wacom->serial[0] = get_unaligned_le64(p: &data[99]); |
1323 | wacom->id[0] = get_unaligned_le16(p: &data[107]); |
1324 | pen_frame_len = 14; |
1325 | pen_frames = 7; |
1326 | } else { |
1327 | wacom->serial[0] = get_unaligned_le64(p: &data[33]); |
1328 | wacom->id[0] = get_unaligned_le16(p: &data[41]); |
1329 | pen_frame_len = 8; |
1330 | pen_frames = 4; |
1331 | } |
1332 | |
1333 | if (wacom->serial[0] >> 52 == 1) { |
1334 | /* Add back in missing bits of ID for non-USI pens */ |
1335 | wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF; |
1336 | } |
1337 | |
1338 | /* number of valid frames */ |
1339 | for (i = 0; i < pen_frames; i++) { |
1340 | unsigned char *frame = &data[i*pen_frame_len + 1]; |
1341 | bool valid = frame[0] & 0x80; |
1342 | |
1343 | if (valid) |
1344 | number_of_valid_frames++; |
1345 | } |
1346 | |
1347 | if (number_of_valid_frames) { |
1348 | if (wacom->hid_data.time_delayed) |
1349 | time_interval = ktime_get() - wacom->hid_data.time_delayed; |
1350 | time_interval = div_u64(dividend: time_interval, divisor: number_of_valid_frames); |
1351 | wacom->hid_data.time_delayed = time_packet_received; |
1352 | } |
1353 | |
1354 | for (i = 0; i < number_of_valid_frames; i++) { |
1355 | unsigned char *frame = &data[i*pen_frame_len + 1]; |
1356 | bool valid = frame[0] & 0x80; |
1357 | bool prox = frame[0] & 0x40; |
1358 | bool range = frame[0] & 0x20; |
1359 | bool invert = frame[0] & 0x10; |
1360 | int frames_number_reversed = number_of_valid_frames - i - 1; |
1361 | ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval; |
1362 | |
1363 | if (!valid) |
1364 | continue; |
1365 | |
1366 | if (!prox) { |
1367 | wacom->shared->stylus_in_proximity = false; |
1368 | wacom_exit_report(wacom); |
1369 | input_sync(dev: pen_input); |
1370 | |
1371 | wacom->tool[0] = 0; |
1372 | wacom->id[0] = 0; |
1373 | wacom->serial[0] = 0; |
1374 | wacom->hid_data.time_delayed = 0; |
1375 | return; |
1376 | } |
1377 | |
1378 | if (range) { |
1379 | if (!wacom->tool[0]) { /* first in range */ |
1380 | /* Going into range select tool */ |
1381 | if (invert) |
1382 | wacom->tool[0] = BTN_TOOL_RUBBER; |
1383 | else if (wacom->id[0]) |
1384 | wacom->tool[0] = wacom_intuos_get_tool_type(tool_id: wacom->id[0]); |
1385 | else |
1386 | wacom->tool[0] = BTN_TOOL_PEN; |
1387 | } |
1388 | |
1389 | input_report_abs(dev: pen_input, ABS_X, value: get_unaligned_le16(p: &frame[1])); |
1390 | input_report_abs(dev: pen_input, ABS_Y, value: get_unaligned_le16(p: &frame[3])); |
1391 | |
1392 | if (wacom->features.type == INTUOSP2_BT || |
1393 | wacom->features.type == INTUOSP2S_BT) { |
1394 | /* Fix rotation alignment: userspace expects zero at left */ |
1395 | int16_t rotation = |
1396 | (int16_t)get_unaligned_le16(p: &frame[9]); |
1397 | rotation += 1800/4; |
1398 | |
1399 | if (rotation > 899) |
1400 | rotation -= 1800; |
1401 | |
1402 | input_report_abs(dev: pen_input, ABS_TILT_X, |
1403 | value: (char)frame[7]); |
1404 | input_report_abs(dev: pen_input, ABS_TILT_Y, |
1405 | value: (char)frame[8]); |
1406 | input_report_abs(dev: pen_input, ABS_Z, value: rotation); |
1407 | input_report_abs(dev: pen_input, ABS_WHEEL, |
1408 | value: get_unaligned_le16(p: &frame[11])); |
1409 | } |
1410 | } |
1411 | |
1412 | if (wacom->tool[0]) { |
1413 | input_report_abs(dev: pen_input, ABS_PRESSURE, value: get_unaligned_le16(p: &frame[5])); |
1414 | if (wacom->features.type == INTUOSP2_BT || |
1415 | wacom->features.type == INTUOSP2S_BT) { |
1416 | input_report_abs(dev: pen_input, ABS_DISTANCE, |
1417 | value: range ? frame[13] : wacom->features.distance_max); |
1418 | } else { |
1419 | input_report_abs(dev: pen_input, ABS_DISTANCE, |
1420 | value: range ? frame[7] : wacom->features.distance_max); |
1421 | } |
1422 | |
1423 | input_report_key(dev: pen_input, BTN_TOUCH, value: frame[0] & 0x09); |
1424 | input_report_key(dev: pen_input, BTN_STYLUS, value: frame[0] & 0x02); |
1425 | input_report_key(dev: pen_input, BTN_STYLUS2, value: frame[0] & 0x04); |
1426 | |
1427 | input_report_key(dev: pen_input, code: wacom->tool[0], value: prox); |
1428 | input_event(dev: pen_input, EV_MSC, MSC_SERIAL, value: wacom->serial[0]); |
1429 | input_report_abs(dev: pen_input, ABS_MISC, |
1430 | value: wacom_intuos_id_mangle(tool_id: wacom->id[0])); /* report tool id */ |
1431 | } |
1432 | |
1433 | wacom->shared->stylus_in_proximity = prox; |
1434 | |
1435 | /* add timestamp to unpack the frames */ |
1436 | input_set_timestamp(dev: pen_input, timestamp: event_timestamp); |
1437 | |
1438 | input_sync(dev: pen_input); |
1439 | } |
1440 | } |
1441 | |
1442 | static void wacom_intuos_pro2_bt_touch(struct wacom_wac *wacom) |
1443 | { |
1444 | const int finger_touch_len = 8; |
1445 | const int finger_frames = 4; |
1446 | const int finger_frame_len = 43; |
1447 | |
1448 | struct input_dev *touch_input = wacom->touch_input; |
1449 | unsigned char *data = wacom->data; |
1450 | int num_contacts_left = 5; |
1451 | int i, j; |
1452 | |
1453 | for (i = 0; i < finger_frames; i++) { |
1454 | unsigned char *frame = &data[i*finger_frame_len + 109]; |
1455 | int current_num_contacts = frame[0] & 0x7F; |
1456 | int contacts_to_send; |
1457 | |
1458 | if (!(frame[0] & 0x80)) |
1459 | continue; |
1460 | |
1461 | /* |
1462 | * First packet resets the counter since only the first |
1463 | * packet in series will have non-zero current_num_contacts. |
1464 | */ |
1465 | if (current_num_contacts) |
1466 | wacom->num_contacts_left = current_num_contacts; |
1467 | |
1468 | contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); |
1469 | |
1470 | for (j = 0; j < contacts_to_send; j++) { |
1471 | unsigned char *touch = &frame[j*finger_touch_len + 1]; |
1472 | int slot = input_mt_get_slot_by_key(dev: touch_input, key: touch[0]); |
1473 | int x = get_unaligned_le16(p: &touch[2]); |
1474 | int y = get_unaligned_le16(p: &touch[4]); |
1475 | int w = touch[6] * input_abs_get_res(dev: touch_input, ABS_MT_POSITION_X); |
1476 | int h = touch[7] * input_abs_get_res(dev: touch_input, ABS_MT_POSITION_Y); |
1477 | |
1478 | if (slot < 0) |
1479 | continue; |
1480 | |
1481 | input_mt_slot(dev: touch_input, slot); |
1482 | input_mt_report_slot_state(dev: touch_input, MT_TOOL_FINGER, active: touch[1] & 0x01); |
1483 | input_report_abs(dev: touch_input, ABS_MT_POSITION_X, value: x); |
1484 | input_report_abs(dev: touch_input, ABS_MT_POSITION_Y, value: y); |
1485 | input_report_abs(dev: touch_input, ABS_MT_TOUCH_MAJOR, max(w, h)); |
1486 | input_report_abs(dev: touch_input, ABS_MT_TOUCH_MINOR, min(w, h)); |
1487 | input_report_abs(dev: touch_input, ABS_MT_ORIENTATION, value: w > h); |
1488 | } |
1489 | |
1490 | input_mt_sync_frame(dev: touch_input); |
1491 | |
1492 | wacom->num_contacts_left -= contacts_to_send; |
1493 | if (wacom->num_contacts_left <= 0) { |
1494 | wacom->num_contacts_left = 0; |
1495 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
1496 | input_sync(dev: touch_input); |
1497 | } |
1498 | } |
1499 | |
1500 | if (wacom->num_contacts_left == 0) { |
1501 | // Be careful that we don't accidentally call input_sync with |
1502 | // only a partial set of fingers of processed |
1503 | input_report_switch(dev: touch_input, SW_MUTE_DEVICE, value: !(data[281] >> 7)); |
1504 | input_sync(dev: touch_input); |
1505 | } |
1506 | |
1507 | } |
1508 | |
1509 | static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom) |
1510 | { |
1511 | struct input_dev *pad_input = wacom->pad_input; |
1512 | unsigned char *data = wacom->data; |
1513 | int nbuttons = wacom->features.numbered_buttons; |
1514 | |
1515 | int expresskeys = data[282]; |
1516 | int center = (data[281] & 0x40) >> 6; |
1517 | int ring = data[285] & 0x7F; |
1518 | bool ringstatus = data[285] & 0x80; |
1519 | bool prox = expresskeys || center || ringstatus; |
1520 | |
1521 | /* Fix touchring data: userspace expects 0 at left and increasing clockwise */ |
1522 | ring = 71 - ring; |
1523 | ring += 3*72/16; |
1524 | if (ring > 71) |
1525 | ring -= 72; |
1526 | |
1527 | wacom_report_numbered_buttons(input_dev: pad_input, button_count: nbuttons, |
1528 | mask: expresskeys | (center << (nbuttons - 1))); |
1529 | |
1530 | input_report_abs(dev: pad_input, ABS_WHEEL, value: ringstatus ? ring : 0); |
1531 | |
1532 | input_report_key(dev: pad_input, code: wacom->tool[1], value: prox ? 1 : 0); |
1533 | input_report_abs(dev: pad_input, ABS_MISC, value: prox ? PAD_DEVICE_ID : 0); |
1534 | input_event(dev: pad_input, EV_MSC, MSC_SERIAL, value: 0xffffffff); |
1535 | |
1536 | input_sync(dev: pad_input); |
1537 | } |
1538 | |
1539 | static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom) |
1540 | { |
1541 | unsigned char *data = wacom->data; |
1542 | |
1543 | bool chg = data[284] & 0x80; |
1544 | int battery_status = data[284] & 0x7F; |
1545 | |
1546 | wacom_notify_battery(wacom_wac: wacom, WACOM_POWER_SUPPLY_STATUS_AUTO, |
1547 | bat_capacity: battery_status, bat_charging: chg, bat_connected: 1, ps_connected: chg); |
1548 | } |
1549 | |
1550 | static void wacom_intuos_gen3_bt_pad(struct wacom_wac *wacom) |
1551 | { |
1552 | struct input_dev *pad_input = wacom->pad_input; |
1553 | unsigned char *data = wacom->data; |
1554 | |
1555 | int buttons = data[44]; |
1556 | |
1557 | wacom_report_numbered_buttons(input_dev: pad_input, button_count: 4, mask: buttons); |
1558 | |
1559 | input_report_key(dev: pad_input, code: wacom->tool[1], value: buttons ? 1 : 0); |
1560 | input_report_abs(dev: pad_input, ABS_MISC, value: buttons ? PAD_DEVICE_ID : 0); |
1561 | input_event(dev: pad_input, EV_MSC, MSC_SERIAL, value: 0xffffffff); |
1562 | |
1563 | input_sync(dev: pad_input); |
1564 | } |
1565 | |
1566 | static void wacom_intuos_gen3_bt_battery(struct wacom_wac *wacom) |
1567 | { |
1568 | unsigned char *data = wacom->data; |
1569 | |
1570 | bool chg = data[45] & 0x80; |
1571 | int battery_status = data[45] & 0x7F; |
1572 | |
1573 | wacom_notify_battery(wacom_wac: wacom, WACOM_POWER_SUPPLY_STATUS_AUTO, |
1574 | bat_capacity: battery_status, bat_charging: chg, bat_connected: 1, ps_connected: chg); |
1575 | } |
1576 | |
1577 | static int wacom_intuos_pro2_bt_irq(struct wacom_wac *wacom, size_t len) |
1578 | { |
1579 | unsigned char *data = wacom->data; |
1580 | |
1581 | if (data[0] != 0x80 && data[0] != 0x81) { |
1582 | dev_dbg(wacom->pen_input->dev.parent, |
1583 | "%s: received unknown report #%d\n" , __func__, data[0]); |
1584 | return 0; |
1585 | } |
1586 | |
1587 | wacom_intuos_pro2_bt_pen(wacom); |
1588 | if (wacom->features.type == INTUOSP2_BT || |
1589 | wacom->features.type == INTUOSP2S_BT) { |
1590 | wacom_intuos_pro2_bt_touch(wacom); |
1591 | wacom_intuos_pro2_bt_pad(wacom); |
1592 | wacom_intuos_pro2_bt_battery(wacom); |
1593 | } else { |
1594 | wacom_intuos_gen3_bt_pad(wacom); |
1595 | wacom_intuos_gen3_bt_battery(wacom); |
1596 | } |
1597 | return 0; |
1598 | } |
1599 | |
1600 | static int wacom_24hdt_irq(struct wacom_wac *wacom) |
1601 | { |
1602 | struct input_dev *input = wacom->touch_input; |
1603 | unsigned char *data = wacom->data; |
1604 | int i; |
1605 | int current_num_contacts = data[61]; |
1606 | int contacts_to_send = 0; |
1607 | int num_contacts_left = 4; /* maximum contacts per packet */ |
1608 | int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET; |
1609 | int y_offset = 2; |
1610 | |
1611 | if (touch_is_muted(wacom_wac: wacom) && !wacom->shared->touch_down) |
1612 | return 0; |
1613 | |
1614 | if (wacom->features.type == WACOM_27QHDT) { |
1615 | current_num_contacts = data[63]; |
1616 | num_contacts_left = 10; |
1617 | byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET; |
1618 | y_offset = 0; |
1619 | } |
1620 | |
1621 | /* |
1622 | * First packet resets the counter since only the first |
1623 | * packet in series will have non-zero current_num_contacts. |
1624 | */ |
1625 | if (current_num_contacts) |
1626 | wacom->num_contacts_left = current_num_contacts; |
1627 | |
1628 | contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); |
1629 | |
1630 | for (i = 0; i < contacts_to_send; i++) { |
1631 | int offset = (byte_per_packet * i) + 1; |
1632 | bool touch = (data[offset] & 0x1) && report_touch_events(wacom); |
1633 | int slot = input_mt_get_slot_by_key(dev: input, key: data[offset + 1]); |
1634 | |
1635 | if (slot < 0) |
1636 | continue; |
1637 | input_mt_slot(dev: input, slot); |
1638 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch); |
1639 | |
1640 | if (touch) { |
1641 | int t_x = get_unaligned_le16(p: &data[offset + 2]); |
1642 | int t_y = get_unaligned_le16(p: &data[offset + 4 + y_offset]); |
1643 | |
1644 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: t_x); |
1645 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: t_y); |
1646 | |
1647 | if (wacom->features.type != WACOM_27QHDT) { |
1648 | int c_x = get_unaligned_le16(p: &data[offset + 4]); |
1649 | int c_y = get_unaligned_le16(p: &data[offset + 8]); |
1650 | int w = get_unaligned_le16(p: &data[offset + 10]); |
1651 | int h = get_unaligned_le16(p: &data[offset + 12]); |
1652 | |
1653 | input_report_abs(dev: input, ABS_MT_TOUCH_MAJOR, min(w,h)); |
1654 | input_report_abs(dev: input, ABS_MT_WIDTH_MAJOR, |
1655 | min(w, h) + int_dist(x1: t_x, y1: t_y, x2: c_x, y2: c_y)); |
1656 | input_report_abs(dev: input, ABS_MT_WIDTH_MINOR, min(w, h)); |
1657 | input_report_abs(dev: input, ABS_MT_ORIENTATION, value: w > h); |
1658 | } |
1659 | } |
1660 | } |
1661 | input_mt_sync_frame(dev: input); |
1662 | |
1663 | wacom->num_contacts_left -= contacts_to_send; |
1664 | if (wacom->num_contacts_left <= 0) { |
1665 | wacom->num_contacts_left = 0; |
1666 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
1667 | } |
1668 | return 1; |
1669 | } |
1670 | |
1671 | static int wacom_mt_touch(struct wacom_wac *wacom) |
1672 | { |
1673 | struct input_dev *input = wacom->touch_input; |
1674 | unsigned char *data = wacom->data; |
1675 | int i; |
1676 | int current_num_contacts = data[2]; |
1677 | int contacts_to_send = 0; |
1678 | int x_offset = 0; |
1679 | |
1680 | /* MTTPC does not support Height and Width */ |
1681 | if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B) |
1682 | x_offset = -4; |
1683 | |
1684 | /* |
1685 | * First packet resets the counter since only the first |
1686 | * packet in series will have non-zero current_num_contacts. |
1687 | */ |
1688 | if (current_num_contacts) |
1689 | wacom->num_contacts_left = current_num_contacts; |
1690 | |
1691 | /* There are at most 5 contacts per packet */ |
1692 | contacts_to_send = min(5, wacom->num_contacts_left); |
1693 | |
1694 | for (i = 0; i < contacts_to_send; i++) { |
1695 | int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3; |
1696 | bool touch = (data[offset] & 0x1) && report_touch_events(wacom); |
1697 | int id = get_unaligned_le16(p: &data[offset + 1]); |
1698 | int slot = input_mt_get_slot_by_key(dev: input, key: id); |
1699 | |
1700 | if (slot < 0) |
1701 | continue; |
1702 | |
1703 | input_mt_slot(dev: input, slot); |
1704 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch); |
1705 | if (touch) { |
1706 | int x = get_unaligned_le16(p: &data[offset + x_offset + 7]); |
1707 | int y = get_unaligned_le16(p: &data[offset + x_offset + 9]); |
1708 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: x); |
1709 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: y); |
1710 | } |
1711 | } |
1712 | input_mt_sync_frame(dev: input); |
1713 | |
1714 | wacom->num_contacts_left -= contacts_to_send; |
1715 | if (wacom->num_contacts_left <= 0) { |
1716 | wacom->num_contacts_left = 0; |
1717 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
1718 | } |
1719 | return 1; |
1720 | } |
1721 | |
1722 | static int wacom_tpc_mt_touch(struct wacom_wac *wacom) |
1723 | { |
1724 | struct input_dev *input = wacom->touch_input; |
1725 | unsigned char *data = wacom->data; |
1726 | int i; |
1727 | |
1728 | for (i = 0; i < 2; i++) { |
1729 | int p = data[1] & (1 << i); |
1730 | bool touch = p && report_touch_events(wacom); |
1731 | |
1732 | input_mt_slot(dev: input, slot: i); |
1733 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch); |
1734 | if (touch) { |
1735 | int x = le16_to_cpup(p: (__le16 *)&data[i * 2 + 2]) & 0x7fff; |
1736 | int y = le16_to_cpup(p: (__le16 *)&data[i * 2 + 6]) & 0x7fff; |
1737 | |
1738 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: x); |
1739 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: y); |
1740 | } |
1741 | } |
1742 | input_mt_sync_frame(dev: input); |
1743 | |
1744 | /* keep touch state for pen event */ |
1745 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
1746 | |
1747 | return 1; |
1748 | } |
1749 | |
1750 | static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) |
1751 | { |
1752 | unsigned char *data = wacom->data; |
1753 | struct input_dev *input = wacom->touch_input; |
1754 | bool prox = report_touch_events(wacom); |
1755 | int x = 0, y = 0; |
1756 | |
1757 | if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) |
1758 | return 0; |
1759 | |
1760 | if (len == WACOM_PKGLEN_TPC1FG) { |
1761 | prox = prox && (data[0] & 0x01); |
1762 | x = get_unaligned_le16(p: &data[1]); |
1763 | y = get_unaligned_le16(p: &data[3]); |
1764 | } else if (len == WACOM_PKGLEN_TPC1FG_B) { |
1765 | prox = prox && (data[2] & 0x01); |
1766 | x = get_unaligned_le16(p: &data[3]); |
1767 | y = get_unaligned_le16(p: &data[5]); |
1768 | } else { |
1769 | prox = prox && (data[1] & 0x01); |
1770 | x = le16_to_cpup(p: (__le16 *)&data[2]); |
1771 | y = le16_to_cpup(p: (__le16 *)&data[4]); |
1772 | } |
1773 | |
1774 | if (prox) { |
1775 | input_report_abs(dev: input, ABS_X, value: x); |
1776 | input_report_abs(dev: input, ABS_Y, value: y); |
1777 | } |
1778 | input_report_key(dev: input, BTN_TOUCH, value: prox); |
1779 | |
1780 | /* keep touch state for pen events */ |
1781 | wacom->shared->touch_down = prox; |
1782 | |
1783 | return 1; |
1784 | } |
1785 | |
1786 | static int wacom_tpc_pen(struct wacom_wac *wacom) |
1787 | { |
1788 | unsigned char *data = wacom->data; |
1789 | struct input_dev *input = wacom->pen_input; |
1790 | bool prox = data[1] & 0x20; |
1791 | |
1792 | if (!wacom->shared->stylus_in_proximity) /* first in prox */ |
1793 | /* Going into proximity select tool */ |
1794 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
1795 | |
1796 | /* keep pen state for touch events */ |
1797 | wacom->shared->stylus_in_proximity = prox; |
1798 | |
1799 | /* send pen events only when touch is up or forced out |
1800 | * or touch arbitration is off |
1801 | */ |
1802 | if (!delay_pen_events(wacom)) { |
1803 | input_report_key(dev: input, BTN_STYLUS, value: data[1] & 0x02); |
1804 | input_report_key(dev: input, BTN_STYLUS2, value: data[1] & 0x10); |
1805 | input_report_abs(dev: input, ABS_X, le16_to_cpup(p: (__le16 *)&data[2])); |
1806 | input_report_abs(dev: input, ABS_Y, le16_to_cpup(p: (__le16 *)&data[4])); |
1807 | input_report_abs(dev: input, ABS_PRESSURE, value: ((data[7] & 0x07) << 8) | data[6]); |
1808 | input_report_key(dev: input, BTN_TOUCH, value: data[1] & 0x05); |
1809 | input_report_key(dev: input, code: wacom->tool[0], value: prox); |
1810 | return 1; |
1811 | } |
1812 | |
1813 | return 0; |
1814 | } |
1815 | |
1816 | static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) |
1817 | { |
1818 | unsigned char *data = wacom->data; |
1819 | |
1820 | if (wacom->pen_input) { |
1821 | dev_dbg(wacom->pen_input->dev.parent, |
1822 | "%s: received report #%d\n" , __func__, data[0]); |
1823 | |
1824 | if (len == WACOM_PKGLEN_PENABLED || |
1825 | data[0] == WACOM_REPORT_PENABLED) |
1826 | return wacom_tpc_pen(wacom); |
1827 | } |
1828 | else if (wacom->touch_input) { |
1829 | dev_dbg(wacom->touch_input->dev.parent, |
1830 | "%s: received report #%d\n" , __func__, data[0]); |
1831 | |
1832 | switch (len) { |
1833 | case WACOM_PKGLEN_TPC1FG: |
1834 | return wacom_tpc_single_touch(wacom, len); |
1835 | |
1836 | case WACOM_PKGLEN_TPC2FG: |
1837 | return wacom_tpc_mt_touch(wacom); |
1838 | |
1839 | default: |
1840 | switch (data[0]) { |
1841 | case WACOM_REPORT_TPC1FG: |
1842 | case WACOM_REPORT_TPCHID: |
1843 | case WACOM_REPORT_TPCST: |
1844 | case WACOM_REPORT_TPC1FGE: |
1845 | return wacom_tpc_single_touch(wacom, len); |
1846 | |
1847 | case WACOM_REPORT_TPCMT: |
1848 | case WACOM_REPORT_TPCMT2: |
1849 | return wacom_mt_touch(wacom); |
1850 | |
1851 | } |
1852 | } |
1853 | } |
1854 | |
1855 | return 0; |
1856 | } |
1857 | |
1858 | static int wacom_offset_rotation(struct input_dev *input, struct hid_usage *usage, |
1859 | int value, int num, int denom) |
1860 | { |
1861 | struct input_absinfo *abs = &input->absinfo[usage->code]; |
1862 | int range = (abs->maximum - abs->minimum + 1); |
1863 | |
1864 | value += num*range/denom; |
1865 | if (value > abs->maximum) |
1866 | value -= range; |
1867 | else if (value < abs->minimum) |
1868 | value += range; |
1869 | return value; |
1870 | } |
1871 | |
1872 | int wacom_equivalent_usage(int usage) |
1873 | { |
1874 | if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { |
1875 | int subpage = (usage & 0xFF00) << 8; |
1876 | int subusage = (usage & 0xFF); |
1877 | |
1878 | if (subpage == WACOM_HID_SP_PAD || |
1879 | subpage == WACOM_HID_SP_BUTTON || |
1880 | subpage == WACOM_HID_SP_DIGITIZER || |
1881 | subpage == WACOM_HID_SP_DIGITIZERINFO || |
1882 | usage == WACOM_HID_WD_SENSE || |
1883 | usage == WACOM_HID_WD_SERIALHI || |
1884 | usage == WACOM_HID_WD_TOOLTYPE || |
1885 | usage == WACOM_HID_WD_DISTANCE || |
1886 | usage == WACOM_HID_WD_TOUCHSTRIP || |
1887 | usage == WACOM_HID_WD_TOUCHSTRIP2 || |
1888 | usage == WACOM_HID_WD_TOUCHRING || |
1889 | usage == WACOM_HID_WD_TOUCHRINGSTATUS || |
1890 | usage == WACOM_HID_WD_REPORT_VALID || |
1891 | usage == WACOM_HID_WD_BARRELSWITCH3 || |
1892 | usage == WACOM_HID_WD_SEQUENCENUMBER) { |
1893 | return usage; |
1894 | } |
1895 | |
1896 | if (subpage == HID_UP_UNDEFINED) |
1897 | subpage = HID_UP_DIGITIZER; |
1898 | |
1899 | return subpage | subusage; |
1900 | } |
1901 | |
1902 | if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMTOUCH) { |
1903 | int subpage = (usage & 0xFF00) << 8; |
1904 | int subusage = (usage & 0xFF); |
1905 | |
1906 | if (usage == WACOM_HID_WT_REPORT_VALID) |
1907 | return usage; |
1908 | |
1909 | if (subpage == HID_UP_UNDEFINED) |
1910 | subpage = WACOM_HID_SP_DIGITIZER; |
1911 | |
1912 | return subpage | subusage; |
1913 | } |
1914 | |
1915 | return usage; |
1916 | } |
1917 | |
1918 | static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, |
1919 | struct hid_field *field, __u8 type, __u16 code, int fuzz) |
1920 | { |
1921 | struct wacom *wacom = input_get_drvdata(dev: input); |
1922 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
1923 | struct wacom_features *features = &wacom_wac->features; |
1924 | int fmin = field->logical_minimum; |
1925 | int fmax = field->logical_maximum; |
1926 | unsigned int equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
1927 | int resolution_code = code; |
1928 | int resolution = hidinput_calc_abs_res(field, code: resolution_code); |
1929 | |
1930 | if (equivalent_usage == HID_DG_TWIST) { |
1931 | resolution_code = ABS_RZ; |
1932 | } |
1933 | |
1934 | if (equivalent_usage == HID_GD_X) { |
1935 | fmin += features->offset_left; |
1936 | fmax -= features->offset_right; |
1937 | } |
1938 | if (equivalent_usage == HID_GD_Y) { |
1939 | fmin += features->offset_top; |
1940 | fmax -= features->offset_bottom; |
1941 | } |
1942 | |
1943 | usage->type = type; |
1944 | usage->code = code; |
1945 | |
1946 | switch (type) { |
1947 | case EV_ABS: |
1948 | input_set_abs_params(dev: input, axis: code, min: fmin, max: fmax, fuzz, flat: 0); |
1949 | |
1950 | /* older tablet may miss physical usage */ |
1951 | if ((code == ABS_X || code == ABS_Y) && !resolution) { |
1952 | resolution = WACOM_INTUOS_RES; |
1953 | hid_warn(input, |
1954 | "Wacom usage (%d) missing resolution \n" , |
1955 | code); |
1956 | } |
1957 | input_abs_set_res(dev: input, axis: code, val: resolution); |
1958 | break; |
1959 | case EV_KEY: |
1960 | case EV_MSC: |
1961 | case EV_SW: |
1962 | input_set_capability(dev: input, type, code); |
1963 | break; |
1964 | } |
1965 | } |
1966 | |
1967 | static void wacom_wac_battery_usage_mapping(struct hid_device *hdev, |
1968 | struct hid_field *field, struct hid_usage *usage) |
1969 | { |
1970 | return; |
1971 | } |
1972 | |
1973 | static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field, |
1974 | struct hid_usage *usage, __s32 value) |
1975 | { |
1976 | struct wacom *wacom = hid_get_drvdata(hdev); |
1977 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
1978 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
1979 | |
1980 | switch (equivalent_usage) { |
1981 | case HID_DG_BATTERYSTRENGTH: |
1982 | if (value == 0) { |
1983 | wacom_wac->hid_data.bat_status = POWER_SUPPLY_STATUS_UNKNOWN; |
1984 | } |
1985 | else { |
1986 | value = value * 100 / (field->logical_maximum - field->logical_minimum); |
1987 | wacom_wac->hid_data.battery_capacity = value; |
1988 | wacom_wac->hid_data.bat_connected = 1; |
1989 | wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; |
1990 | } |
1991 | wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; |
1992 | break; |
1993 | case WACOM_HID_WD_BATTERY_LEVEL: |
1994 | value = value * 100 / (field->logical_maximum - field->logical_minimum); |
1995 | wacom_wac->hid_data.battery_capacity = value; |
1996 | wacom_wac->hid_data.bat_connected = 1; |
1997 | wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; |
1998 | wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; |
1999 | break; |
2000 | case WACOM_HID_WD_BATTERY_CHARGING: |
2001 | wacom_wac->hid_data.bat_charging = value; |
2002 | wacom_wac->hid_data.ps_connected = value; |
2003 | wacom_wac->hid_data.bat_connected = 1; |
2004 | wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO; |
2005 | wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY; |
2006 | break; |
2007 | } |
2008 | } |
2009 | |
2010 | static void wacom_wac_battery_pre_report(struct hid_device *hdev, |
2011 | struct hid_report *report) |
2012 | { |
2013 | return; |
2014 | } |
2015 | |
2016 | static void wacom_wac_battery_report(struct hid_device *hdev, |
2017 | struct hid_report *report) |
2018 | { |
2019 | struct wacom *wacom = hid_get_drvdata(hdev); |
2020 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2021 | |
2022 | int status = wacom_wac->hid_data.bat_status; |
2023 | int capacity = wacom_wac->hid_data.battery_capacity; |
2024 | bool charging = wacom_wac->hid_data.bat_charging; |
2025 | bool connected = wacom_wac->hid_data.bat_connected; |
2026 | bool powered = wacom_wac->hid_data.ps_connected; |
2027 | |
2028 | wacom_notify_battery(wacom_wac, bat_status: status, bat_capacity: capacity, bat_charging: charging, |
2029 | bat_connected: connected, ps_connected: powered); |
2030 | } |
2031 | |
2032 | static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, |
2033 | struct hid_field *field, struct hid_usage *usage) |
2034 | { |
2035 | struct wacom *wacom = hid_get_drvdata(hdev); |
2036 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2037 | struct wacom_features *features = &wacom_wac->features; |
2038 | struct input_dev *input = wacom_wac->pad_input; |
2039 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2040 | |
2041 | switch (equivalent_usage) { |
2042 | case WACOM_HID_WD_ACCELEROMETER_X: |
2043 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); |
2044 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, fuzz: 0); |
2045 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2046 | break; |
2047 | case WACOM_HID_WD_ACCELEROMETER_Y: |
2048 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); |
2049 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, fuzz: 0); |
2050 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2051 | break; |
2052 | case WACOM_HID_WD_ACCELEROMETER_Z: |
2053 | __set_bit(INPUT_PROP_ACCELEROMETER, input->propbit); |
2054 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, fuzz: 0); |
2055 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2056 | break; |
2057 | case WACOM_HID_WD_BUTTONCENTER: |
2058 | case WACOM_HID_WD_BUTTONHOME: |
2059 | case WACOM_HID_WD_BUTTONUP: |
2060 | case WACOM_HID_WD_BUTTONDOWN: |
2061 | case WACOM_HID_WD_BUTTONLEFT: |
2062 | case WACOM_HID_WD_BUTTONRIGHT: |
2063 | wacom_map_usage(input, usage, field, EV_KEY, |
2064 | code: wacom_numbered_button_to_key(n: features->numbered_buttons), |
2065 | fuzz: 0); |
2066 | features->numbered_buttons++; |
2067 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2068 | break; |
2069 | case WACOM_HID_WD_MUTE_DEVICE: |
2070 | /* softkey touch switch */ |
2071 | wacom_wac->is_soft_touch_switch = true; |
2072 | fallthrough; |
2073 | case WACOM_HID_WD_TOUCHONOFF: |
2074 | /* |
2075 | * These two usages, which are used to mute touch events, come |
2076 | * from the pad packet, but are reported on the touch |
2077 | * interface. Because the touch interface may not have |
2078 | * been created yet, we cannot call wacom_map_usage(). In |
2079 | * order to process the usages when we receive them, we set |
2080 | * the usage type and code directly. |
2081 | */ |
2082 | wacom_wac->has_mute_touch_switch = true; |
2083 | usage->type = EV_SW; |
2084 | usage->code = SW_MUTE_DEVICE; |
2085 | break; |
2086 | case WACOM_HID_WD_TOUCHSTRIP: |
2087 | wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, fuzz: 0); |
2088 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2089 | break; |
2090 | case WACOM_HID_WD_TOUCHSTRIP2: |
2091 | wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, fuzz: 0); |
2092 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2093 | break; |
2094 | case WACOM_HID_WD_TOUCHRING: |
2095 | wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, fuzz: 0); |
2096 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2097 | break; |
2098 | case WACOM_HID_WD_TOUCHRINGSTATUS: |
2099 | /* |
2100 | * Only set up type/code association. Completely mapping |
2101 | * this usage may overwrite the axis resolution and range. |
2102 | */ |
2103 | usage->type = EV_ABS; |
2104 | usage->code = ABS_WHEEL; |
2105 | set_bit(EV_ABS, addr: input->evbit); |
2106 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2107 | break; |
2108 | case WACOM_HID_WD_BUTTONCONFIG: |
2109 | wacom_map_usage(input, usage, field, EV_KEY, KEY_BUTTONCONFIG, fuzz: 0); |
2110 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2111 | break; |
2112 | case WACOM_HID_WD_ONSCREEN_KEYBOARD: |
2113 | wacom_map_usage(input, usage, field, EV_KEY, KEY_ONSCREEN_KEYBOARD, fuzz: 0); |
2114 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2115 | break; |
2116 | case WACOM_HID_WD_CONTROLPANEL: |
2117 | wacom_map_usage(input, usage, field, EV_KEY, KEY_CONTROLPANEL, fuzz: 0); |
2118 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2119 | break; |
2120 | case WACOM_HID_WD_MODE_CHANGE: |
2121 | /* do not overwrite previous data */ |
2122 | if (!wacom_wac->has_mode_change) { |
2123 | wacom_wac->has_mode_change = true; |
2124 | wacom_wac->is_direct_mode = true; |
2125 | } |
2126 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2127 | break; |
2128 | } |
2129 | |
2130 | switch (equivalent_usage & 0xfffffff0) { |
2131 | case WACOM_HID_WD_EXPRESSKEY00: |
2132 | wacom_map_usage(input, usage, field, EV_KEY, |
2133 | code: wacom_numbered_button_to_key(n: features->numbered_buttons), |
2134 | fuzz: 0); |
2135 | features->numbered_buttons++; |
2136 | features->device_type |= WACOM_DEVICETYPE_PAD; |
2137 | break; |
2138 | } |
2139 | } |
2140 | |
2141 | static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field, |
2142 | struct hid_usage *usage, __s32 value) |
2143 | { |
2144 | struct wacom *wacom = hid_get_drvdata(hdev); |
2145 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2146 | struct input_dev *input = wacom_wac->pad_input; |
2147 | struct wacom_features *features = &wacom_wac->features; |
2148 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2149 | int i; |
2150 | bool do_report = false; |
2151 | |
2152 | /* |
2153 | * Avoid reporting this event and setting inrange_state if this usage |
2154 | * hasn't been mapped. |
2155 | */ |
2156 | if (!usage->type && equivalent_usage != WACOM_HID_WD_MODE_CHANGE) |
2157 | return; |
2158 | |
2159 | if (wacom_equivalent_usage(usage: field->physical) == HID_DG_TABLETFUNCTIONKEY) { |
2160 | if (usage->hid != WACOM_HID_WD_TOUCHRING) |
2161 | wacom_wac->hid_data.inrange_state |= value; |
2162 | } |
2163 | |
2164 | /* Process touch switch state first since it is reported through touch interface, |
2165 | * which is indepentent of pad interface. In the case when there are no other pad |
2166 | * events, the pad interface will not even be created. |
2167 | */ |
2168 | if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) || |
2169 | (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) { |
2170 | if (wacom_wac->shared->touch_input) { |
2171 | bool *is_touch_on = &wacom_wac->shared->is_touch_on; |
2172 | |
2173 | if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value) |
2174 | *is_touch_on = !(*is_touch_on); |
2175 | else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF) |
2176 | *is_touch_on = value; |
2177 | |
2178 | input_report_switch(dev: wacom_wac->shared->touch_input, |
2179 | SW_MUTE_DEVICE, value: !(*is_touch_on)); |
2180 | input_sync(dev: wacom_wac->shared->touch_input); |
2181 | } |
2182 | return; |
2183 | } |
2184 | |
2185 | if (!input) |
2186 | return; |
2187 | |
2188 | switch (equivalent_usage) { |
2189 | case WACOM_HID_WD_TOUCHRING: |
2190 | /* |
2191 | * Userspace expects touchrings to increase in value with |
2192 | * clockwise gestures and have their zero point at the |
2193 | * tablet's left. HID events "should" be clockwise- |
2194 | * increasing and zero at top, though the MobileStudio |
2195 | * Pro and 2nd-gen Intuos Pro don't do this... |
2196 | */ |
2197 | if (hdev->vendor == 0x56a && |
2198 | (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */ |
2199 | hdev->product == 0x357 || hdev->product == 0x358 || /* Intuos Pro 2 */ |
2200 | hdev->product == 0x392 || /* Intuos Pro 2 */ |
2201 | hdev->product == 0x398 || hdev->product == 0x399 || /* MobileStudio Pro */ |
2202 | hdev->product == 0x3AA)) { /* MobileStudio Pro */ |
2203 | value = (field->logical_maximum - value); |
2204 | |
2205 | if (hdev->product == 0x357 || hdev->product == 0x358 || |
2206 | hdev->product == 0x392) |
2207 | value = wacom_offset_rotation(input, usage, value, num: 3, denom: 16); |
2208 | else if (hdev->product == 0x34d || hdev->product == 0x34e || |
2209 | hdev->product == 0x398 || hdev->product == 0x399 || |
2210 | hdev->product == 0x3AA) |
2211 | value = wacom_offset_rotation(input, usage, value, num: 1, denom: 2); |
2212 | } |
2213 | else { |
2214 | value = wacom_offset_rotation(input, usage, value, num: 1, denom: 4); |
2215 | } |
2216 | do_report = true; |
2217 | break; |
2218 | case WACOM_HID_WD_TOUCHRINGSTATUS: |
2219 | if (!value) |
2220 | input_event(dev: input, type: usage->type, code: usage->code, value: 0); |
2221 | break; |
2222 | |
2223 | case WACOM_HID_WD_MODE_CHANGE: |
2224 | if (wacom_wac->is_direct_mode != value) { |
2225 | wacom_wac->is_direct_mode = value; |
2226 | wacom_schedule_work(wacom_wac: &wacom->wacom_wac, which: WACOM_WORKER_MODE_CHANGE); |
2227 | } |
2228 | break; |
2229 | |
2230 | case WACOM_HID_WD_BUTTONCENTER: |
2231 | for (i = 0; i < wacom->led.count; i++) |
2232 | wacom_update_led(wacom, button_count: features->numbered_buttons, |
2233 | mask: value, group: i); |
2234 | fallthrough; |
2235 | default: |
2236 | do_report = true; |
2237 | break; |
2238 | } |
2239 | |
2240 | if (do_report) { |
2241 | input_event(dev: input, type: usage->type, code: usage->code, value); |
2242 | if (value) |
2243 | wacom_wac->hid_data.pad_input_event_flag = true; |
2244 | } |
2245 | } |
2246 | |
2247 | static void wacom_wac_pad_pre_report(struct hid_device *hdev, |
2248 | struct hid_report *report) |
2249 | { |
2250 | struct wacom *wacom = hid_get_drvdata(hdev); |
2251 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2252 | |
2253 | wacom_wac->hid_data.inrange_state = 0; |
2254 | } |
2255 | |
2256 | static void wacom_wac_pad_report(struct hid_device *hdev, |
2257 | struct hid_report *report, struct hid_field *field) |
2258 | { |
2259 | struct wacom *wacom = hid_get_drvdata(hdev); |
2260 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2261 | struct input_dev *input = wacom_wac->pad_input; |
2262 | bool active = wacom_wac->hid_data.inrange_state != 0; |
2263 | |
2264 | /* report prox for expresskey events */ |
2265 | if (wacom_wac->hid_data.pad_input_event_flag) { |
2266 | input_event(dev: input, EV_ABS, ABS_MISC, value: active ? PAD_DEVICE_ID : 0); |
2267 | input_sync(dev: input); |
2268 | if (!active) |
2269 | wacom_wac->hid_data.pad_input_event_flag = false; |
2270 | } |
2271 | } |
2272 | |
2273 | static void wacom_set_barrel_switch3_usage(struct wacom_wac *wacom_wac) |
2274 | { |
2275 | struct input_dev *input = wacom_wac->pen_input; |
2276 | struct wacom_features *features = &wacom_wac->features; |
2277 | |
2278 | if (!(features->quirks & WACOM_QUIRK_AESPEN) && |
2279 | wacom_wac->hid_data.barrelswitch && |
2280 | wacom_wac->hid_data.barrelswitch2 && |
2281 | wacom_wac->hid_data.serialhi && |
2282 | !wacom_wac->hid_data.barrelswitch3) { |
2283 | input_set_capability(dev: input, EV_KEY, BTN_STYLUS3); |
2284 | features->quirks |= WACOM_QUIRK_PEN_BUTTON3; |
2285 | } |
2286 | } |
2287 | |
2288 | static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, |
2289 | struct hid_field *field, struct hid_usage *usage) |
2290 | { |
2291 | struct wacom *wacom = hid_get_drvdata(hdev); |
2292 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2293 | struct wacom_features *features = &wacom_wac->features; |
2294 | struct input_dev *input = wacom_wac->pen_input; |
2295 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2296 | |
2297 | switch (equivalent_usage) { |
2298 | case HID_GD_X: |
2299 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, fuzz: 4); |
2300 | break; |
2301 | case HID_GD_Y: |
2302 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, fuzz: 4); |
2303 | break; |
2304 | case WACOM_HID_WD_DISTANCE: |
2305 | case HID_GD_Z: |
2306 | wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, fuzz: 0); |
2307 | break; |
2308 | case HID_DG_TIPPRESSURE: |
2309 | wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, fuzz: 0); |
2310 | break; |
2311 | case HID_DG_INRANGE: |
2312 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, fuzz: 0); |
2313 | break; |
2314 | case HID_DG_INVERT: |
2315 | wacom_map_usage(input, usage, field, EV_KEY, |
2316 | BTN_TOOL_RUBBER, fuzz: 0); |
2317 | break; |
2318 | case HID_DG_TILT_X: |
2319 | wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, fuzz: 0); |
2320 | break; |
2321 | case HID_DG_TILT_Y: |
2322 | wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, fuzz: 0); |
2323 | break; |
2324 | case HID_DG_TWIST: |
2325 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, fuzz: 0); |
2326 | break; |
2327 | case HID_DG_ERASER: |
2328 | input_set_capability(dev: input, EV_KEY, BTN_TOOL_RUBBER); |
2329 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, fuzz: 0); |
2330 | break; |
2331 | case HID_DG_TIPSWITCH: |
2332 | input_set_capability(dev: input, EV_KEY, BTN_TOOL_PEN); |
2333 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, fuzz: 0); |
2334 | break; |
2335 | case HID_DG_BARRELSWITCH: |
2336 | wacom_wac->hid_data.barrelswitch = true; |
2337 | wacom_set_barrel_switch3_usage(wacom_wac); |
2338 | wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, fuzz: 0); |
2339 | break; |
2340 | case HID_DG_BARRELSWITCH2: |
2341 | wacom_wac->hid_data.barrelswitch2 = true; |
2342 | wacom_set_barrel_switch3_usage(wacom_wac); |
2343 | wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, fuzz: 0); |
2344 | break; |
2345 | case HID_DG_TOOLSERIALNUMBER: |
2346 | features->quirks |= WACOM_QUIRK_TOOLSERIAL; |
2347 | wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, fuzz: 0); |
2348 | break; |
2349 | case HID_DG_SCANTIME: |
2350 | wacom_map_usage(input, usage, field, EV_MSC, MSC_TIMESTAMP, fuzz: 0); |
2351 | break; |
2352 | case WACOM_HID_WD_SENSE: |
2353 | features->quirks |= WACOM_QUIRK_SENSE; |
2354 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, fuzz: 0); |
2355 | break; |
2356 | case WACOM_HID_WD_SERIALHI: |
2357 | wacom_wac->hid_data.serialhi = true; |
2358 | wacom_set_barrel_switch3_usage(wacom_wac); |
2359 | wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, fuzz: 0); |
2360 | break; |
2361 | case WACOM_HID_WD_FINGERWHEEL: |
2362 | input_set_capability(dev: input, EV_KEY, BTN_TOOL_AIRBRUSH); |
2363 | wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, fuzz: 0); |
2364 | break; |
2365 | case WACOM_HID_WD_BARRELSWITCH3: |
2366 | wacom_wac->hid_data.barrelswitch3 = true; |
2367 | wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS3, fuzz: 0); |
2368 | features->quirks &= ~WACOM_QUIRK_PEN_BUTTON3; |
2369 | break; |
2370 | } |
2371 | } |
2372 | |
2373 | static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, |
2374 | struct hid_usage *usage, __s32 value) |
2375 | { |
2376 | struct wacom *wacom = hid_get_drvdata(hdev); |
2377 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2378 | struct wacom_features *features = &wacom_wac->features; |
2379 | struct input_dev *input = wacom_wac->pen_input; |
2380 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2381 | |
2382 | if (wacom_wac->is_invalid_bt_frame) |
2383 | return; |
2384 | |
2385 | switch (equivalent_usage) { |
2386 | case HID_GD_Z: |
2387 | /* |
2388 | * HID_GD_Z "should increase as the control's position is |
2389 | * moved from high to low", while ABS_DISTANCE instead |
2390 | * increases in value as the tool moves from low to high. |
2391 | */ |
2392 | value = field->logical_maximum - value; |
2393 | break; |
2394 | case HID_DG_INRANGE: |
2395 | mod_timer(timer: &wacom->idleprox_timer, expires: jiffies + msecs_to_jiffies(m: 100)); |
2396 | wacom_wac->hid_data.inrange_state = value; |
2397 | if (!(features->quirks & WACOM_QUIRK_SENSE)) |
2398 | wacom_wac->hid_data.sense_state = value; |
2399 | return; |
2400 | case HID_DG_INVERT: |
2401 | wacom_wac->hid_data.invert_state = value; |
2402 | return; |
2403 | case HID_DG_ERASER: |
2404 | case HID_DG_TIPSWITCH: |
2405 | wacom_wac->hid_data.tipswitch |= value; |
2406 | return; |
2407 | case HID_DG_BARRELSWITCH: |
2408 | wacom_wac->hid_data.barrelswitch = value; |
2409 | return; |
2410 | case HID_DG_BARRELSWITCH2: |
2411 | wacom_wac->hid_data.barrelswitch2 = value; |
2412 | return; |
2413 | case HID_DG_TOOLSERIALNUMBER: |
2414 | if (value) { |
2415 | wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL); |
2416 | wacom_wac->serial[0] |= wacom_s32tou(value, n: field->report_size); |
2417 | } |
2418 | return; |
2419 | case HID_DG_TWIST: |
2420 | /* don't modify the value if the pen doesn't support the feature */ |
2421 | if (!wacom_is_art_pen(tool_id: wacom_wac->id[0])) return; |
2422 | |
2423 | /* |
2424 | * Userspace expects pen twist to have its zero point when |
2425 | * the buttons/finger is on the tablet's left. HID values |
2426 | * are zero when buttons are toward the top. |
2427 | */ |
2428 | value = wacom_offset_rotation(input, usage, value, num: 1, denom: 4); |
2429 | break; |
2430 | case WACOM_HID_WD_SENSE: |
2431 | wacom_wac->hid_data.sense_state = value; |
2432 | return; |
2433 | case WACOM_HID_WD_SERIALHI: |
2434 | if (value) { |
2435 | __u32 raw_value = wacom_s32tou(value, n: field->report_size); |
2436 | |
2437 | wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF); |
2438 | wacom_wac->serial[0] |= ((__u64)raw_value) << 32; |
2439 | /* |
2440 | * Non-USI EMR devices may contain additional tool type |
2441 | * information here. See WACOM_HID_WD_TOOLTYPE case for |
2442 | * more details. |
2443 | */ |
2444 | if (value >> 20 == 1) { |
2445 | wacom_wac->id[0] |= raw_value & 0xFFFFF; |
2446 | } |
2447 | } |
2448 | return; |
2449 | case WACOM_HID_WD_TOOLTYPE: |
2450 | /* |
2451 | * Some devices (MobileStudio Pro, and possibly later |
2452 | * devices as well) do not return the complete tool |
2453 | * type in their WACOM_HID_WD_TOOLTYPE usage. Use a |
2454 | * bitwise OR so the complete value can be built |
2455 | * up over time :( |
2456 | */ |
2457 | wacom_wac->id[0] |= wacom_s32tou(value, n: field->report_size); |
2458 | return; |
2459 | case WACOM_HID_WD_OFFSETLEFT: |
2460 | if (features->offset_left && value != features->offset_left) |
2461 | hid_warn(hdev, "%s: overriding existing left offset " |
2462 | "%d -> %d\n" , __func__, value, |
2463 | features->offset_left); |
2464 | features->offset_left = value; |
2465 | return; |
2466 | case WACOM_HID_WD_OFFSETRIGHT: |
2467 | if (features->offset_right && value != features->offset_right) |
2468 | hid_warn(hdev, "%s: overriding existing right offset " |
2469 | "%d -> %d\n" , __func__, value, |
2470 | features->offset_right); |
2471 | features->offset_right = value; |
2472 | return; |
2473 | case WACOM_HID_WD_OFFSETTOP: |
2474 | if (features->offset_top && value != features->offset_top) |
2475 | hid_warn(hdev, "%s: overriding existing top offset " |
2476 | "%d -> %d\n" , __func__, value, |
2477 | features->offset_top); |
2478 | features->offset_top = value; |
2479 | return; |
2480 | case WACOM_HID_WD_OFFSETBOTTOM: |
2481 | if (features->offset_bottom && value != features->offset_bottom) |
2482 | hid_warn(hdev, "%s: overriding existing bottom offset " |
2483 | "%d -> %d\n" , __func__, value, |
2484 | features->offset_bottom); |
2485 | features->offset_bottom = value; |
2486 | return; |
2487 | case WACOM_HID_WD_REPORT_VALID: |
2488 | wacom_wac->is_invalid_bt_frame = !value; |
2489 | return; |
2490 | case WACOM_HID_WD_BARRELSWITCH3: |
2491 | wacom_wac->hid_data.barrelswitch3 = value; |
2492 | return; |
2493 | case WACOM_HID_WD_SEQUENCENUMBER: |
2494 | if (wacom_wac->hid_data.sequence_number != value) |
2495 | hid_warn(hdev, "Dropped %hu packets" , (unsigned short)(value - wacom_wac->hid_data.sequence_number)); |
2496 | wacom_wac->hid_data.sequence_number = value + 1; |
2497 | return; |
2498 | } |
2499 | |
2500 | /* send pen events only when touch is up or forced out |
2501 | * or touch arbitration is off |
2502 | */ |
2503 | if (!usage->type || delay_pen_events(wacom: wacom_wac)) |
2504 | return; |
2505 | |
2506 | /* send pen events only when the pen is in range */ |
2507 | if (wacom_wac->hid_data.inrange_state) |
2508 | input_event(dev: input, type: usage->type, code: usage->code, value); |
2509 | else if (wacom_wac->shared->stylus_in_proximity && !wacom_wac->hid_data.sense_state) |
2510 | input_event(dev: input, type: usage->type, code: usage->code, value: 0); |
2511 | } |
2512 | |
2513 | static void wacom_wac_pen_pre_report(struct hid_device *hdev, |
2514 | struct hid_report *report) |
2515 | { |
2516 | struct wacom *wacom = hid_get_drvdata(hdev); |
2517 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2518 | |
2519 | wacom_wac->is_invalid_bt_frame = false; |
2520 | return; |
2521 | } |
2522 | |
2523 | static void wacom_wac_pen_report(struct hid_device *hdev, |
2524 | struct hid_report *report) |
2525 | { |
2526 | struct wacom *wacom = hid_get_drvdata(hdev); |
2527 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2528 | struct input_dev *input = wacom_wac->pen_input; |
2529 | bool range = wacom_wac->hid_data.inrange_state; |
2530 | bool sense = wacom_wac->hid_data.sense_state; |
2531 | |
2532 | if (wacom_wac->is_invalid_bt_frame) |
2533 | return; |
2534 | |
2535 | if (!wacom_wac->tool[0] && range) { /* first in range */ |
2536 | /* Going into range select tool */ |
2537 | if (wacom_wac->hid_data.invert_state) |
2538 | wacom_wac->tool[0] = BTN_TOOL_RUBBER; |
2539 | else if (wacom_wac->id[0]) |
2540 | wacom_wac->tool[0] = wacom_intuos_get_tool_type(tool_id: wacom_wac->id[0]); |
2541 | else |
2542 | wacom_wac->tool[0] = BTN_TOOL_PEN; |
2543 | } |
2544 | |
2545 | /* keep pen state for touch events */ |
2546 | wacom_wac->shared->stylus_in_proximity = sense; |
2547 | |
2548 | if (!delay_pen_events(wacom: wacom_wac) && wacom_wac->tool[0]) { |
2549 | int id = wacom_wac->id[0]; |
2550 | if (wacom_wac->features.quirks & WACOM_QUIRK_PEN_BUTTON3) { |
2551 | int sw_state = wacom_wac->hid_data.barrelswitch | |
2552 | (wacom_wac->hid_data.barrelswitch2 << 1); |
2553 | wacom_wac->hid_data.barrelswitch = sw_state == 1; |
2554 | wacom_wac->hid_data.barrelswitch2 = sw_state == 2; |
2555 | wacom_wac->hid_data.barrelswitch3 = sw_state == 3; |
2556 | } |
2557 | input_report_key(dev: input, BTN_STYLUS, value: wacom_wac->hid_data.barrelswitch); |
2558 | input_report_key(dev: input, BTN_STYLUS2, value: wacom_wac->hid_data.barrelswitch2); |
2559 | input_report_key(dev: input, BTN_STYLUS3, value: wacom_wac->hid_data.barrelswitch3); |
2560 | |
2561 | /* |
2562 | * Non-USI EMR tools should have their IDs mangled to |
2563 | * match the legacy behavior of wacom_intuos_general |
2564 | */ |
2565 | if (wacom_wac->serial[0] >> 52 == 1) |
2566 | id = wacom_intuos_id_mangle(tool_id: id); |
2567 | |
2568 | /* |
2569 | * To ensure compatibility with xf86-input-wacom, we should |
2570 | * report the BTN_TOOL_* event prior to the ABS_MISC or |
2571 | * MSC_SERIAL events. |
2572 | */ |
2573 | input_report_key(dev: input, BTN_TOUCH, |
2574 | value: wacom_wac->hid_data.tipswitch); |
2575 | input_report_key(dev: input, code: wacom_wac->tool[0], value: sense); |
2576 | if (wacom_wac->serial[0]) { |
2577 | input_event(dev: input, EV_MSC, MSC_SERIAL, value: wacom_wac->serial[0]); |
2578 | input_report_abs(dev: input, ABS_MISC, value: sense ? id : 0); |
2579 | } |
2580 | |
2581 | wacom_wac->hid_data.tipswitch = false; |
2582 | |
2583 | input_sync(dev: input); |
2584 | } |
2585 | |
2586 | if (!sense) { |
2587 | wacom_wac->tool[0] = 0; |
2588 | wacom_wac->id[0] = 0; |
2589 | wacom_wac->serial[0] = 0; |
2590 | } |
2591 | } |
2592 | |
2593 | static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, |
2594 | struct hid_field *field, struct hid_usage *usage) |
2595 | { |
2596 | struct wacom *wacom = hid_get_drvdata(hdev); |
2597 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2598 | struct input_dev *input = wacom_wac->touch_input; |
2599 | unsigned touch_max = wacom_wac->features.touch_max; |
2600 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2601 | |
2602 | switch (equivalent_usage) { |
2603 | case HID_GD_X: |
2604 | if (touch_max == 1) |
2605 | wacom_map_usage(input, usage, field, EV_ABS, ABS_X, fuzz: 4); |
2606 | else |
2607 | wacom_map_usage(input, usage, field, EV_ABS, |
2608 | ABS_MT_POSITION_X, fuzz: 4); |
2609 | break; |
2610 | case HID_GD_Y: |
2611 | if (touch_max == 1) |
2612 | wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, fuzz: 4); |
2613 | else |
2614 | wacom_map_usage(input, usage, field, EV_ABS, |
2615 | ABS_MT_POSITION_Y, fuzz: 4); |
2616 | break; |
2617 | case HID_DG_WIDTH: |
2618 | case HID_DG_HEIGHT: |
2619 | wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, fuzz: 0); |
2620 | wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, fuzz: 0); |
2621 | input_set_abs_params(dev: input, ABS_MT_ORIENTATION, min: 0, max: 1, fuzz: 0, flat: 0); |
2622 | break; |
2623 | case HID_DG_TIPSWITCH: |
2624 | wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, fuzz: 0); |
2625 | break; |
2626 | case HID_DG_CONTACTCOUNT: |
2627 | wacom_wac->hid_data.cc_report = field->report->id; |
2628 | wacom_wac->hid_data.cc_index = field->index; |
2629 | wacom_wac->hid_data.cc_value_index = usage->usage_index; |
2630 | break; |
2631 | case HID_DG_CONTACTID: |
2632 | if ((field->logical_maximum - field->logical_minimum) < touch_max) { |
2633 | /* |
2634 | * The HID descriptor for G11 sensors leaves logical |
2635 | * maximum set to '1' despite it being a multitouch |
2636 | * device. Override to a sensible number. |
2637 | */ |
2638 | field->logical_maximum = 255; |
2639 | } |
2640 | break; |
2641 | case HID_DG_SCANTIME: |
2642 | wacom_map_usage(input, usage, field, EV_MSC, MSC_TIMESTAMP, fuzz: 0); |
2643 | break; |
2644 | } |
2645 | } |
2646 | |
2647 | static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, |
2648 | struct input_dev *input) |
2649 | { |
2650 | struct hid_data *hid_data = &wacom_wac->hid_data; |
2651 | bool mt = wacom_wac->features.touch_max > 1; |
2652 | bool prox = hid_data->tipswitch && |
2653 | report_touch_events(wacom: wacom_wac); |
2654 | |
2655 | if (touch_is_muted(wacom_wac)) { |
2656 | if (!wacom_wac->shared->touch_down) |
2657 | return; |
2658 | prox = false; |
2659 | } |
2660 | |
2661 | wacom_wac->hid_data.num_received++; |
2662 | if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected) |
2663 | return; |
2664 | |
2665 | if (mt) { |
2666 | int slot; |
2667 | |
2668 | slot = input_mt_get_slot_by_key(dev: input, key: hid_data->id); |
2669 | if (slot < 0) { |
2670 | return; |
2671 | } else { |
2672 | struct input_mt_slot *ps = &input->mt->slots[slot]; |
2673 | int mt_id = input_mt_get_value(slot: ps, ABS_MT_TRACKING_ID); |
2674 | |
2675 | if (!prox && mt_id < 0) { |
2676 | // No data to send for this slot; short-circuit |
2677 | return; |
2678 | } |
2679 | } |
2680 | |
2681 | input_mt_slot(dev: input, slot); |
2682 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: prox); |
2683 | } |
2684 | else { |
2685 | input_report_key(dev: input, BTN_TOUCH, value: prox); |
2686 | } |
2687 | |
2688 | if (prox) { |
2689 | input_report_abs(dev: input, code: mt ? ABS_MT_POSITION_X : ABS_X, |
2690 | value: hid_data->x); |
2691 | input_report_abs(dev: input, code: mt ? ABS_MT_POSITION_Y : ABS_Y, |
2692 | value: hid_data->y); |
2693 | |
2694 | if (test_bit(ABS_MT_TOUCH_MAJOR, input->absbit)) { |
2695 | input_report_abs(dev: input, ABS_MT_TOUCH_MAJOR, max(hid_data->width, hid_data->height)); |
2696 | input_report_abs(dev: input, ABS_MT_TOUCH_MINOR, min(hid_data->width, hid_data->height)); |
2697 | if (hid_data->width != hid_data->height) |
2698 | input_report_abs(dev: input, ABS_MT_ORIENTATION, value: hid_data->width <= hid_data->height ? 0 : 1); |
2699 | } |
2700 | } |
2701 | } |
2702 | |
2703 | static bool wacom_wac_slot_is_active(struct input_dev *dev, int key) |
2704 | { |
2705 | struct input_mt *mt = dev->mt; |
2706 | struct input_mt_slot *s; |
2707 | |
2708 | if (!mt) |
2709 | return false; |
2710 | |
2711 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { |
2712 | if (s->key == key && |
2713 | input_mt_get_value(slot: s, ABS_MT_TRACKING_ID) >= 0) { |
2714 | return true; |
2715 | } |
2716 | } |
2717 | |
2718 | return false; |
2719 | } |
2720 | |
2721 | static void wacom_wac_finger_event(struct hid_device *hdev, |
2722 | struct hid_field *field, struct hid_usage *usage, __s32 value) |
2723 | { |
2724 | struct wacom *wacom = hid_get_drvdata(hdev); |
2725 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2726 | unsigned equivalent_usage = wacom_equivalent_usage(usage: usage->hid); |
2727 | struct wacom_features *features = &wacom->wacom_wac.features; |
2728 | |
2729 | if (touch_is_muted(wacom_wac) && !wacom_wac->shared->touch_down) |
2730 | return; |
2731 | |
2732 | if (wacom_wac->is_invalid_bt_frame) |
2733 | return; |
2734 | |
2735 | switch (equivalent_usage) { |
2736 | case HID_DG_CONFIDENCE: |
2737 | wacom_wac->hid_data.confidence = value; |
2738 | break; |
2739 | case HID_GD_X: |
2740 | wacom_wac->hid_data.x = value; |
2741 | break; |
2742 | case HID_GD_Y: |
2743 | wacom_wac->hid_data.y = value; |
2744 | break; |
2745 | case HID_DG_WIDTH: |
2746 | wacom_wac->hid_data.width = value; |
2747 | break; |
2748 | case HID_DG_HEIGHT: |
2749 | wacom_wac->hid_data.height = value; |
2750 | break; |
2751 | case HID_DG_CONTACTID: |
2752 | wacom_wac->hid_data.id = value; |
2753 | break; |
2754 | case HID_DG_TIPSWITCH: |
2755 | wacom_wac->hid_data.tipswitch = value; |
2756 | break; |
2757 | case WACOM_HID_WT_REPORT_VALID: |
2758 | wacom_wac->is_invalid_bt_frame = !value; |
2759 | return; |
2760 | case HID_DG_CONTACTMAX: |
2761 | if (!features->touch_max) { |
2762 | features->touch_max = value; |
2763 | } else { |
2764 | hid_warn(hdev, "%s: ignoring attempt to overwrite non-zero touch_max " |
2765 | "%d -> %d\n" , __func__, features->touch_max, value); |
2766 | } |
2767 | return; |
2768 | } |
2769 | |
2770 | if (usage->usage_index + 1 == field->report_count) { |
2771 | if (equivalent_usage == wacom_wac->hid_data.last_slot_field) { |
2772 | bool touch_removed = wacom_wac_slot_is_active(dev: wacom_wac->touch_input, |
2773 | key: wacom_wac->hid_data.id) && !wacom_wac->hid_data.tipswitch; |
2774 | |
2775 | if (wacom_wac->hid_data.confidence || touch_removed) { |
2776 | wacom_wac_finger_slot(wacom_wac, input: wacom_wac->touch_input); |
2777 | } |
2778 | } |
2779 | } |
2780 | } |
2781 | |
2782 | static void wacom_wac_finger_pre_report(struct hid_device *hdev, |
2783 | struct hid_report *report) |
2784 | { |
2785 | struct wacom *wacom = hid_get_drvdata(hdev); |
2786 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2787 | struct hid_data* hid_data = &wacom_wac->hid_data; |
2788 | int i; |
2789 | |
2790 | if (touch_is_muted(wacom_wac) && !wacom_wac->shared->touch_down) |
2791 | return; |
2792 | |
2793 | wacom_wac->is_invalid_bt_frame = false; |
2794 | |
2795 | hid_data->confidence = true; |
2796 | |
2797 | hid_data->cc_report = 0; |
2798 | hid_data->cc_index = -1; |
2799 | hid_data->cc_value_index = -1; |
2800 | |
2801 | for (i = 0; i < report->maxfield; i++) { |
2802 | struct hid_field *field = report->field[i]; |
2803 | int j; |
2804 | |
2805 | for (j = 0; j < field->maxusage; j++) { |
2806 | struct hid_usage *usage = &field->usage[j]; |
2807 | unsigned int equivalent_usage = |
2808 | wacom_equivalent_usage(usage: usage->hid); |
2809 | |
2810 | switch (equivalent_usage) { |
2811 | case HID_GD_X: |
2812 | case HID_GD_Y: |
2813 | case HID_DG_WIDTH: |
2814 | case HID_DG_HEIGHT: |
2815 | case HID_DG_CONTACTID: |
2816 | case HID_DG_INRANGE: |
2817 | case HID_DG_INVERT: |
2818 | case HID_DG_TIPSWITCH: |
2819 | hid_data->last_slot_field = equivalent_usage; |
2820 | break; |
2821 | case HID_DG_CONTACTCOUNT: |
2822 | hid_data->cc_report = report->id; |
2823 | hid_data->cc_index = i; |
2824 | hid_data->cc_value_index = j; |
2825 | break; |
2826 | } |
2827 | } |
2828 | } |
2829 | |
2830 | if (hid_data->cc_report != 0 && |
2831 | hid_data->cc_index >= 0) { |
2832 | struct hid_field *field = report->field[hid_data->cc_index]; |
2833 | int value = field->value[hid_data->cc_value_index]; |
2834 | if (value) { |
2835 | hid_data->num_expected = value; |
2836 | hid_data->num_received = 0; |
2837 | } |
2838 | } |
2839 | else { |
2840 | hid_data->num_expected = wacom_wac->features.touch_max; |
2841 | hid_data->num_received = 0; |
2842 | } |
2843 | } |
2844 | |
2845 | static void wacom_wac_finger_report(struct hid_device *hdev, |
2846 | struct hid_report *report) |
2847 | { |
2848 | struct wacom *wacom = hid_get_drvdata(hdev); |
2849 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2850 | struct input_dev *input = wacom_wac->touch_input; |
2851 | unsigned touch_max = wacom_wac->features.touch_max; |
2852 | |
2853 | /* if there was nothing to process, don't send an empty sync */ |
2854 | if (wacom_wac->hid_data.num_expected == 0) |
2855 | return; |
2856 | |
2857 | /* If more packets of data are expected, give us a chance to |
2858 | * process them rather than immediately syncing a partial |
2859 | * update. |
2860 | */ |
2861 | if (wacom_wac->hid_data.num_received < wacom_wac->hid_data.num_expected) |
2862 | return; |
2863 | |
2864 | if (touch_max > 1) |
2865 | input_mt_sync_frame(dev: input); |
2866 | |
2867 | input_sync(dev: input); |
2868 | wacom_wac->hid_data.num_received = 0; |
2869 | wacom_wac->hid_data.num_expected = 0; |
2870 | |
2871 | /* keep touch state for pen event */ |
2872 | wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom: wacom_wac); |
2873 | } |
2874 | |
2875 | void wacom_wac_usage_mapping(struct hid_device *hdev, |
2876 | struct hid_field *field, struct hid_usage *usage) |
2877 | { |
2878 | struct wacom *wacom = hid_get_drvdata(hdev); |
2879 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2880 | struct wacom_features *features = &wacom_wac->features; |
2881 | |
2882 | if (WACOM_DIRECT_DEVICE(field)) |
2883 | features->device_type |= WACOM_DEVICETYPE_DIRECT; |
2884 | |
2885 | /* usage tests must precede field tests */ |
2886 | if (WACOM_BATTERY_USAGE(usage)) |
2887 | wacom_wac_battery_usage_mapping(hdev, field, usage); |
2888 | else if (WACOM_PAD_FIELD(field)) |
2889 | wacom_wac_pad_usage_mapping(hdev, field, usage); |
2890 | else if (WACOM_PEN_FIELD(field)) |
2891 | wacom_wac_pen_usage_mapping(hdev, field, usage); |
2892 | else if (WACOM_FINGER_FIELD(field)) |
2893 | wacom_wac_finger_usage_mapping(hdev, field, usage); |
2894 | } |
2895 | |
2896 | void wacom_wac_event(struct hid_device *hdev, struct hid_field *field, |
2897 | struct hid_usage *usage, __s32 value) |
2898 | { |
2899 | struct wacom *wacom = hid_get_drvdata(hdev); |
2900 | |
2901 | if (wacom->wacom_wac.features.type != HID_GENERIC) |
2902 | return; |
2903 | |
2904 | if (value > field->logical_maximum || value < field->logical_minimum) |
2905 | return; |
2906 | |
2907 | /* usage tests must precede field tests */ |
2908 | if (WACOM_BATTERY_USAGE(usage)) |
2909 | wacom_wac_battery_event(hdev, field, usage, value); |
2910 | else if (WACOM_PAD_FIELD(field)) |
2911 | wacom_wac_pad_event(hdev, field, usage, value); |
2912 | else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) |
2913 | wacom_wac_pen_event(hdev, field, usage, value); |
2914 | else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) |
2915 | wacom_wac_finger_event(hdev, field, usage, value); |
2916 | } |
2917 | |
2918 | static void wacom_report_events(struct hid_device *hdev, |
2919 | struct hid_report *report, int collection_index, |
2920 | int field_index) |
2921 | { |
2922 | int r; |
2923 | |
2924 | for (r = field_index; r < report->maxfield; r++) { |
2925 | struct hid_field *field; |
2926 | unsigned count, n; |
2927 | |
2928 | field = report->field[r]; |
2929 | count = field->report_count; |
2930 | |
2931 | if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) |
2932 | continue; |
2933 | |
2934 | for (n = 0 ; n < count; n++) { |
2935 | if (field->usage[n].collection_index == collection_index) |
2936 | wacom_wac_event(hdev, field, usage: &field->usage[n], |
2937 | value: field->value[n]); |
2938 | else |
2939 | return; |
2940 | } |
2941 | } |
2942 | } |
2943 | |
2944 | static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report, |
2945 | int collection_index, struct hid_field *field, |
2946 | int field_index) |
2947 | { |
2948 | struct wacom *wacom = hid_get_drvdata(hdev); |
2949 | |
2950 | wacom_report_events(hdev, report, collection_index, field_index); |
2951 | |
2952 | /* |
2953 | * Non-input reports may be sent prior to the device being |
2954 | * completely initialized. Since only their events need |
2955 | * to be processed, exit after 'wacom_report_events' has |
2956 | * been called to prevent potential crashes in the report- |
2957 | * processing functions. |
2958 | */ |
2959 | if (report->type != HID_INPUT_REPORT) |
2960 | return -1; |
2961 | |
2962 | if (WACOM_PAD_FIELD(field)) |
2963 | return 0; |
2964 | else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) |
2965 | wacom_wac_pen_report(hdev, report); |
2966 | else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) |
2967 | wacom_wac_finger_report(hdev, report); |
2968 | |
2969 | return 0; |
2970 | } |
2971 | |
2972 | void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) |
2973 | { |
2974 | struct wacom *wacom = hid_get_drvdata(hdev); |
2975 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
2976 | struct hid_field *field; |
2977 | bool pad_in_hid_field = false, pen_in_hid_field = false, |
2978 | finger_in_hid_field = false, true_pad = false; |
2979 | int r; |
2980 | int prev_collection = -1; |
2981 | |
2982 | if (wacom_wac->features.type != HID_GENERIC) |
2983 | return; |
2984 | |
2985 | for (r = 0; r < report->maxfield; r++) { |
2986 | field = report->field[r]; |
2987 | |
2988 | if (WACOM_PAD_FIELD(field)) |
2989 | pad_in_hid_field = true; |
2990 | if (WACOM_PEN_FIELD(field)) |
2991 | pen_in_hid_field = true; |
2992 | if (WACOM_FINGER_FIELD(field)) |
2993 | finger_in_hid_field = true; |
2994 | if (wacom_equivalent_usage(usage: field->physical) == HID_DG_TABLETFUNCTIONKEY) |
2995 | true_pad = true; |
2996 | } |
2997 | |
2998 | wacom_wac_battery_pre_report(hdev, report); |
2999 | |
3000 | if (pad_in_hid_field && wacom->wacom_wac.pad_input) |
3001 | wacom_wac_pad_pre_report(hdev, report); |
3002 | if (pen_in_hid_field && wacom->wacom_wac.pen_input) |
3003 | wacom_wac_pen_pre_report(hdev, report); |
3004 | if (finger_in_hid_field && wacom->wacom_wac.touch_input) |
3005 | wacom_wac_finger_pre_report(hdev, report); |
3006 | |
3007 | for (r = 0; r < report->maxfield; r++) { |
3008 | field = report->field[r]; |
3009 | |
3010 | if (field->usage[0].collection_index != prev_collection) { |
3011 | if (wacom_wac_collection(hdev, report, |
3012 | collection_index: field->usage[0].collection_index, field, field_index: r) < 0) |
3013 | return; |
3014 | prev_collection = field->usage[0].collection_index; |
3015 | } |
3016 | } |
3017 | |
3018 | wacom_wac_battery_report(hdev, report); |
3019 | |
3020 | if (true_pad && wacom->wacom_wac.pad_input) |
3021 | wacom_wac_pad_report(hdev, report, field); |
3022 | } |
3023 | |
3024 | static int wacom_bpt_touch(struct wacom_wac *wacom) |
3025 | { |
3026 | struct wacom_features *features = &wacom->features; |
3027 | struct input_dev *input = wacom->touch_input; |
3028 | struct input_dev *pad_input = wacom->pad_input; |
3029 | unsigned char *data = wacom->data; |
3030 | int i; |
3031 | |
3032 | if (data[0] != 0x02) |
3033 | return 0; |
3034 | |
3035 | for (i = 0; i < 2; i++) { |
3036 | int offset = (data[1] & 0x80) ? (8 * i) : (9 * i); |
3037 | bool touch = report_touch_events(wacom) |
3038 | && (data[offset + 3] & 0x80); |
3039 | |
3040 | input_mt_slot(dev: input, slot: i); |
3041 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch); |
3042 | if (touch) { |
3043 | int x = get_unaligned_be16(p: &data[offset + 3]) & 0x7ff; |
3044 | int y = get_unaligned_be16(p: &data[offset + 5]) & 0x7ff; |
3045 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { |
3046 | x <<= 5; |
3047 | y <<= 5; |
3048 | } |
3049 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: x); |
3050 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: y); |
3051 | } |
3052 | } |
3053 | |
3054 | input_mt_sync_frame(dev: input); |
3055 | |
3056 | input_report_key(dev: pad_input, BTN_LEFT, value: (data[1] & 0x08) != 0); |
3057 | input_report_key(dev: pad_input, BTN_FORWARD, value: (data[1] & 0x04) != 0); |
3058 | input_report_key(dev: pad_input, BTN_BACK, value: (data[1] & 0x02) != 0); |
3059 | input_report_key(dev: pad_input, BTN_RIGHT, value: (data[1] & 0x01) != 0); |
3060 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
3061 | |
3062 | return 1; |
3063 | } |
3064 | |
3065 | static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) |
3066 | { |
3067 | struct wacom_features *features = &wacom->features; |
3068 | struct input_dev *input = wacom->touch_input; |
3069 | bool touch = data[1] & 0x80; |
3070 | int slot = input_mt_get_slot_by_key(dev: input, key: data[0]); |
3071 | |
3072 | if (slot < 0) |
3073 | return; |
3074 | |
3075 | touch = touch && report_touch_events(wacom); |
3076 | |
3077 | input_mt_slot(dev: input, slot); |
3078 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: touch); |
3079 | |
3080 | if (touch) { |
3081 | int x = (data[2] << 4) | (data[4] >> 4); |
3082 | int y = (data[3] << 4) | (data[4] & 0x0f); |
3083 | int width, height; |
3084 | |
3085 | if (features->type >= INTUOSPS && features->type <= INTUOSHT2) { |
3086 | width = data[5] * 100; |
3087 | height = data[6] * 100; |
3088 | } else { |
3089 | /* |
3090 | * "a" is a scaled-down area which we assume is |
3091 | * roughly circular and which can be described as: |
3092 | * a=(pi*r^2)/C. |
3093 | */ |
3094 | int a = data[5]; |
3095 | int x_res = input_abs_get_res(dev: input, ABS_MT_POSITION_X); |
3096 | int y_res = input_abs_get_res(dev: input, ABS_MT_POSITION_Y); |
3097 | width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); |
3098 | height = width * y_res / x_res; |
3099 | } |
3100 | |
3101 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: x); |
3102 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: y); |
3103 | input_report_abs(dev: input, ABS_MT_TOUCH_MAJOR, value: width); |
3104 | input_report_abs(dev: input, ABS_MT_TOUCH_MINOR, value: height); |
3105 | } |
3106 | } |
3107 | |
3108 | static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) |
3109 | { |
3110 | struct input_dev *input = wacom->pad_input; |
3111 | struct wacom_features *features = &wacom->features; |
3112 | |
3113 | if (features->type == INTUOSHT || features->type == INTUOSHT2) { |
3114 | input_report_key(dev: input, BTN_LEFT, value: (data[1] & 0x02) != 0); |
3115 | input_report_key(dev: input, BTN_BACK, value: (data[1] & 0x08) != 0); |
3116 | } else { |
3117 | input_report_key(dev: input, BTN_BACK, value: (data[1] & 0x02) != 0); |
3118 | input_report_key(dev: input, BTN_LEFT, value: (data[1] & 0x08) != 0); |
3119 | } |
3120 | input_report_key(dev: input, BTN_FORWARD, value: (data[1] & 0x04) != 0); |
3121 | input_report_key(dev: input, BTN_RIGHT, value: (data[1] & 0x01) != 0); |
3122 | } |
3123 | |
3124 | static int wacom_bpt3_touch(struct wacom_wac *wacom) |
3125 | { |
3126 | unsigned char *data = wacom->data; |
3127 | int count = data[1] & 0x07; |
3128 | int touch_changed = 0, i; |
3129 | |
3130 | if (data[0] != 0x02) |
3131 | return 0; |
3132 | |
3133 | /* data has up to 7 fixed sized 8-byte messages starting at data[2] */ |
3134 | for (i = 0; i < count; i++) { |
3135 | int offset = (8 * i) + 2; |
3136 | int msg_id = data[offset]; |
3137 | |
3138 | if (msg_id >= 2 && msg_id <= 17) { |
3139 | wacom_bpt3_touch_msg(wacom, data: data + offset); |
3140 | touch_changed++; |
3141 | } else if (msg_id == 128) |
3142 | wacom_bpt3_button_msg(wacom, data: data + offset); |
3143 | |
3144 | } |
3145 | |
3146 | /* only update touch if we actually have a touchpad and touch data changed */ |
3147 | if (wacom->touch_input && touch_changed) { |
3148 | input_mt_sync_frame(dev: wacom->touch_input); |
3149 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
3150 | } |
3151 | |
3152 | return 1; |
3153 | } |
3154 | |
3155 | static int wacom_bpt_pen(struct wacom_wac *wacom) |
3156 | { |
3157 | struct wacom_features *features = &wacom->features; |
3158 | struct input_dev *input = wacom->pen_input; |
3159 | unsigned char *data = wacom->data; |
3160 | int x = 0, y = 0, p = 0, d = 0; |
3161 | bool pen = false, btn1 = false, btn2 = false; |
3162 | bool range, prox, rdy; |
3163 | |
3164 | if (data[0] != WACOM_REPORT_PENABLED) |
3165 | return 0; |
3166 | |
3167 | range = (data[1] & 0x80) == 0x80; |
3168 | prox = (data[1] & 0x40) == 0x40; |
3169 | rdy = (data[1] & 0x20) == 0x20; |
3170 | |
3171 | wacom->shared->stylus_in_proximity = range; |
3172 | if (delay_pen_events(wacom)) |
3173 | return 0; |
3174 | |
3175 | if (rdy) { |
3176 | p = le16_to_cpup(p: (__le16 *)&data[6]); |
3177 | pen = data[1] & 0x01; |
3178 | btn1 = data[1] & 0x02; |
3179 | btn2 = data[1] & 0x04; |
3180 | } |
3181 | if (prox) { |
3182 | x = le16_to_cpup(p: (__le16 *)&data[2]); |
3183 | y = le16_to_cpup(p: (__le16 *)&data[4]); |
3184 | |
3185 | if (data[1] & 0x08) { |
3186 | wacom->tool[0] = BTN_TOOL_RUBBER; |
3187 | wacom->id[0] = ERASER_DEVICE_ID; |
3188 | } else { |
3189 | wacom->tool[0] = BTN_TOOL_PEN; |
3190 | wacom->id[0] = STYLUS_DEVICE_ID; |
3191 | } |
3192 | wacom->reporting_data = true; |
3193 | } |
3194 | if (range) { |
3195 | /* |
3196 | * Convert distance from out prox to distance from tablet. |
3197 | * distance will be greater than distance_max once |
3198 | * touching and applying pressure; do not report negative |
3199 | * distance. |
3200 | */ |
3201 | if (data[8] <= features->distance_max) |
3202 | d = features->distance_max - data[8]; |
3203 | } else { |
3204 | wacom->id[0] = 0; |
3205 | } |
3206 | |
3207 | if (wacom->reporting_data) { |
3208 | input_report_key(dev: input, BTN_TOUCH, value: pen); |
3209 | input_report_key(dev: input, BTN_STYLUS, value: btn1); |
3210 | input_report_key(dev: input, BTN_STYLUS2, value: btn2); |
3211 | |
3212 | if (prox || !range) { |
3213 | input_report_abs(dev: input, ABS_X, value: x); |
3214 | input_report_abs(dev: input, ABS_Y, value: y); |
3215 | } |
3216 | input_report_abs(dev: input, ABS_PRESSURE, value: p); |
3217 | input_report_abs(dev: input, ABS_DISTANCE, value: d); |
3218 | |
3219 | input_report_key(dev: input, code: wacom->tool[0], value: range); /* PEN or RUBBER */ |
3220 | input_report_abs(dev: input, ABS_MISC, value: wacom->id[0]); /* TOOL ID */ |
3221 | } |
3222 | |
3223 | if (!range) { |
3224 | wacom->reporting_data = false; |
3225 | } |
3226 | |
3227 | return 1; |
3228 | } |
3229 | |
3230 | static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) |
3231 | { |
3232 | struct wacom_features *features = &wacom->features; |
3233 | |
3234 | if ((features->type == INTUOSHT2) && |
3235 | (features->device_type & WACOM_DEVICETYPE_PEN)) |
3236 | return wacom_intuos_irq(wacom); |
3237 | else if (len == WACOM_PKGLEN_BBTOUCH) |
3238 | return wacom_bpt_touch(wacom); |
3239 | else if (len == WACOM_PKGLEN_BBTOUCH3) |
3240 | return wacom_bpt3_touch(wacom); |
3241 | else if (len == WACOM_PKGLEN_BBFUN || len == WACOM_PKGLEN_BBPEN) |
3242 | return wacom_bpt_pen(wacom); |
3243 | |
3244 | return 0; |
3245 | } |
3246 | |
3247 | static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom, |
3248 | unsigned char *data) |
3249 | { |
3250 | unsigned char prefix; |
3251 | |
3252 | /* |
3253 | * We need to reroute the event from the debug interface to the |
3254 | * pen interface. |
3255 | * We need to add the report ID to the actual pen report, so we |
3256 | * temporary overwrite the first byte to prevent having to kzalloc/kfree |
3257 | * and memcpy the report. |
3258 | */ |
3259 | prefix = data[0]; |
3260 | data[0] = WACOM_REPORT_BPAD_PEN; |
3261 | |
3262 | /* |
3263 | * actually reroute the event. |
3264 | * No need to check if wacom->shared->pen is valid, hid_input_report() |
3265 | * will check for us. |
3266 | */ |
3267 | hid_input_report(hid: wacom->shared->pen, type: HID_INPUT_REPORT, data, |
3268 | WACOM_PKGLEN_PENABLED, interrupt: 1); |
3269 | |
3270 | data[0] = prefix; |
3271 | } |
3272 | |
3273 | static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom, |
3274 | unsigned char *data) |
3275 | { |
3276 | struct input_dev *input = wacom->touch_input; |
3277 | unsigned char *finger_data, prefix; |
3278 | unsigned id; |
3279 | int x, y; |
3280 | bool valid; |
3281 | |
3282 | prefix = data[0]; |
3283 | |
3284 | for (id = 0; id < wacom->features.touch_max; id++) { |
3285 | valid = !!(prefix & BIT(id)) && |
3286 | report_touch_events(wacom); |
3287 | |
3288 | input_mt_slot(dev: input, slot: id); |
3289 | input_mt_report_slot_state(dev: input, MT_TOOL_FINGER, active: valid); |
3290 | |
3291 | if (!valid) |
3292 | continue; |
3293 | |
3294 | finger_data = data + 1 + id * 3; |
3295 | x = finger_data[0] | ((finger_data[1] & 0x0f) << 8); |
3296 | y = (finger_data[2] << 4) | (finger_data[1] >> 4); |
3297 | |
3298 | input_report_abs(dev: input, ABS_MT_POSITION_X, value: x); |
3299 | input_report_abs(dev: input, ABS_MT_POSITION_Y, value: y); |
3300 | } |
3301 | |
3302 | input_mt_sync_frame(dev: input); |
3303 | |
3304 | input_report_key(dev: input, BTN_LEFT, value: prefix & 0x40); |
3305 | input_report_key(dev: input, BTN_RIGHT, value: prefix & 0x80); |
3306 | |
3307 | /* keep touch state for pen event */ |
3308 | wacom->shared->touch_down = !!prefix && report_touch_events(wacom); |
3309 | |
3310 | return 1; |
3311 | } |
3312 | |
3313 | static int wacom_bamboo_pad_irq(struct wacom_wac *wacom, size_t len) |
3314 | { |
3315 | unsigned char *data = wacom->data; |
3316 | |
3317 | if (!((len == WACOM_PKGLEN_BPAD_TOUCH) || |
3318 | (len == WACOM_PKGLEN_BPAD_TOUCH_USB)) || |
3319 | (data[0] != WACOM_REPORT_BPAD_TOUCH)) |
3320 | return 0; |
3321 | |
3322 | if (data[1] & 0x01) |
3323 | wacom_bamboo_pad_pen_event(wacom, data: &data[1]); |
3324 | |
3325 | if (data[1] & 0x02) |
3326 | return wacom_bamboo_pad_touch_event(wacom, data: &data[9]); |
3327 | |
3328 | return 0; |
3329 | } |
3330 | |
3331 | static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) |
3332 | { |
3333 | unsigned char *data = wacom->data; |
3334 | int connected; |
3335 | |
3336 | if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL) |
3337 | return 0; |
3338 | |
3339 | connected = data[1] & 0x01; |
3340 | if (connected) { |
3341 | int pid, battery, charging; |
3342 | |
3343 | if ((wacom->shared->type == INTUOSHT || |
3344 | wacom->shared->type == INTUOSHT2) && |
3345 | wacom->shared->touch_input && |
3346 | wacom->shared->touch_max) { |
3347 | input_report_switch(dev: wacom->shared->touch_input, |
3348 | SW_MUTE_DEVICE, value: data[5] & 0x40); |
3349 | input_sync(dev: wacom->shared->touch_input); |
3350 | } |
3351 | |
3352 | pid = get_unaligned_be16(p: &data[6]); |
3353 | battery = (data[5] & 0x3f) * 100 / 31; |
3354 | charging = !!(data[5] & 0x80); |
3355 | if (wacom->pid != pid) { |
3356 | wacom->pid = pid; |
3357 | wacom_schedule_work(wacom_wac: wacom, which: WACOM_WORKER_WIRELESS); |
3358 | } |
3359 | |
3360 | wacom_notify_battery(wacom_wac: wacom, WACOM_POWER_SUPPLY_STATUS_AUTO, |
3361 | bat_capacity: battery, bat_charging: charging, bat_connected: 1, ps_connected: 0); |
3362 | |
3363 | } else if (wacom->pid != 0) { |
3364 | /* disconnected while previously connected */ |
3365 | wacom->pid = 0; |
3366 | wacom_schedule_work(wacom_wac: wacom, which: WACOM_WORKER_WIRELESS); |
3367 | wacom_notify_battery(wacom_wac: wacom, bat_status: POWER_SUPPLY_STATUS_UNKNOWN, bat_capacity: 0, bat_charging: 0, bat_connected: 0, ps_connected: 0); |
3368 | } |
3369 | |
3370 | return 0; |
3371 | } |
3372 | |
3373 | static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) |
3374 | { |
3375 | struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); |
3376 | struct wacom_features *features = &wacom_wac->features; |
3377 | unsigned char *data = wacom_wac->data; |
3378 | |
3379 | if (data[0] != WACOM_REPORT_USB) |
3380 | return 0; |
3381 | |
3382 | if ((features->type == INTUOSHT || |
3383 | features->type == INTUOSHT2) && |
3384 | wacom_wac->shared->touch_input && |
3385 | features->touch_max) { |
3386 | input_report_switch(dev: wacom_wac->shared->touch_input, |
3387 | SW_MUTE_DEVICE, value: data[8] & 0x40); |
3388 | input_sync(dev: wacom_wac->shared->touch_input); |
3389 | } |
3390 | |
3391 | if (data[9] & 0x02) { /* wireless module is attached */ |
3392 | int battery = (data[8] & 0x3f) * 100 / 31; |
3393 | bool charging = !!(data[8] & 0x80); |
3394 | |
3395 | features->quirks |= WACOM_QUIRK_BATTERY; |
3396 | wacom_notify_battery(wacom_wac, WACOM_POWER_SUPPLY_STATUS_AUTO, |
3397 | bat_capacity: battery, bat_charging: charging, bat_connected: battery || charging, ps_connected: 1); |
3398 | } |
3399 | else if ((features->quirks & WACOM_QUIRK_BATTERY) && |
3400 | wacom->battery.battery) { |
3401 | features->quirks &= ~WACOM_QUIRK_BATTERY; |
3402 | wacom_notify_battery(wacom_wac, bat_status: POWER_SUPPLY_STATUS_UNKNOWN, bat_capacity: 0, bat_charging: 0, bat_connected: 0, ps_connected: 0); |
3403 | } |
3404 | return 0; |
3405 | } |
3406 | |
3407 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
3408 | { |
3409 | bool sync; |
3410 | |
3411 | switch (wacom_wac->features.type) { |
3412 | case PENPARTNER: |
3413 | sync = wacom_penpartner_irq(wacom: wacom_wac); |
3414 | break; |
3415 | |
3416 | case PL: |
3417 | sync = wacom_pl_irq(wacom: wacom_wac); |
3418 | break; |
3419 | |
3420 | case WACOM_G4: |
3421 | case GRAPHIRE: |
3422 | case GRAPHIRE_BT: |
3423 | case WACOM_MO: |
3424 | sync = wacom_graphire_irq(wacom: wacom_wac); |
3425 | break; |
3426 | |
3427 | case PTU: |
3428 | sync = wacom_ptu_irq(wacom: wacom_wac); |
3429 | break; |
3430 | |
3431 | case DTU: |
3432 | sync = wacom_dtu_irq(wacom: wacom_wac); |
3433 | break; |
3434 | |
3435 | case DTUS: |
3436 | case DTUSX: |
3437 | sync = wacom_dtus_irq(wacom: wacom_wac); |
3438 | break; |
3439 | |
3440 | case INTUOS: |
3441 | case INTUOS3S: |
3442 | case INTUOS3: |
3443 | case INTUOS3L: |
3444 | case INTUOS4S: |
3445 | case INTUOS4: |
3446 | case INTUOS4L: |
3447 | case CINTIQ: |
3448 | case WACOM_BEE: |
3449 | case WACOM_13HD: |
3450 | case WACOM_21UX2: |
3451 | case WACOM_22HD: |
3452 | case WACOM_24HD: |
3453 | case WACOM_27QHD: |
3454 | case DTK: |
3455 | case CINTIQ_HYBRID: |
3456 | case CINTIQ_COMPANION_2: |
3457 | sync = wacom_intuos_irq(wacom: wacom_wac); |
3458 | break; |
3459 | |
3460 | case INTUOS4WL: |
3461 | sync = wacom_intuos_bt_irq(wacom: wacom_wac, len); |
3462 | break; |
3463 | |
3464 | case WACOM_24HDT: |
3465 | case WACOM_27QHDT: |
3466 | sync = wacom_24hdt_irq(wacom: wacom_wac); |
3467 | break; |
3468 | |
3469 | case INTUOS5S: |
3470 | case INTUOS5: |
3471 | case INTUOS5L: |
3472 | case INTUOSPS: |
3473 | case INTUOSPM: |
3474 | case INTUOSPL: |
3475 | if (len == WACOM_PKGLEN_BBTOUCH3) |
3476 | sync = wacom_bpt3_touch(wacom: wacom_wac); |
3477 | else if (wacom_wac->data[0] == WACOM_REPORT_USB) |
3478 | sync = wacom_status_irq(wacom_wac, len); |
3479 | else |
3480 | sync = wacom_intuos_irq(wacom: wacom_wac); |
3481 | break; |
3482 | |
3483 | case INTUOSP2_BT: |
3484 | case INTUOSP2S_BT: |
3485 | case INTUOSHT3_BT: |
3486 | sync = wacom_intuos_pro2_bt_irq(wacom: wacom_wac, len); |
3487 | break; |
3488 | |
3489 | case TABLETPC: |
3490 | case TABLETPCE: |
3491 | case TABLETPC2FG: |
3492 | case MTSCREEN: |
3493 | case MTTPC: |
3494 | case MTTPC_B: |
3495 | sync = wacom_tpc_irq(wacom: wacom_wac, len); |
3496 | break; |
3497 | |
3498 | case BAMBOO_PT: |
3499 | case BAMBOO_PEN: |
3500 | case BAMBOO_TOUCH: |
3501 | case INTUOSHT: |
3502 | case INTUOSHT2: |
3503 | if (wacom_wac->data[0] == WACOM_REPORT_USB) |
3504 | sync = wacom_status_irq(wacom_wac, len); |
3505 | else |
3506 | sync = wacom_bpt_irq(wacom: wacom_wac, len); |
3507 | break; |
3508 | |
3509 | case BAMBOO_PAD: |
3510 | sync = wacom_bamboo_pad_irq(wacom: wacom_wac, len); |
3511 | break; |
3512 | |
3513 | case WIRELESS: |
3514 | sync = wacom_wireless_irq(wacom: wacom_wac, len); |
3515 | break; |
3516 | |
3517 | case REMOTE: |
3518 | sync = false; |
3519 | if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST) |
3520 | wacom_remote_status_irq(wacom_wac, len); |
3521 | else |
3522 | sync = wacom_remote_irq(wacom_wac, len); |
3523 | break; |
3524 | |
3525 | default: |
3526 | sync = false; |
3527 | break; |
3528 | } |
3529 | |
3530 | if (sync) { |
3531 | if (wacom_wac->pen_input) |
3532 | input_sync(dev: wacom_wac->pen_input); |
3533 | if (wacom_wac->touch_input) |
3534 | input_sync(dev: wacom_wac->touch_input); |
3535 | if (wacom_wac->pad_input) |
3536 | input_sync(dev: wacom_wac->pad_input); |
3537 | } |
3538 | } |
3539 | |
3540 | static void wacom_setup_basic_pro_pen(struct wacom_wac *wacom_wac) |
3541 | { |
3542 | struct input_dev *input_dev = wacom_wac->pen_input; |
3543 | |
3544 | input_set_capability(dev: input_dev, EV_MSC, MSC_SERIAL); |
3545 | |
3546 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
3547 | __set_bit(BTN_STYLUS, input_dev->keybit); |
3548 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
3549 | |
3550 | input_set_abs_params(dev: input_dev, ABS_DISTANCE, |
3551 | min: 0, max: wacom_wac->features.distance_max, fuzz: wacom_wac->features.distance_fuzz, flat: 0); |
3552 | } |
3553 | |
3554 | static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) |
3555 | { |
3556 | struct input_dev *input_dev = wacom_wac->pen_input; |
3557 | struct wacom_features *features = &wacom_wac->features; |
3558 | |
3559 | wacom_setup_basic_pro_pen(wacom_wac); |
3560 | |
3561 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
3562 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); |
3563 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); |
3564 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); |
3565 | |
3566 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 1023, fuzz: 0, flat: 0); |
3567 | input_set_abs_params(dev: input_dev, ABS_TILT_X, min: -64, max: 63, fuzz: features->tilt_fuzz, flat: 0); |
3568 | input_abs_set_res(dev: input_dev, ABS_TILT_X, val: 57); |
3569 | input_set_abs_params(dev: input_dev, ABS_TILT_Y, min: -64, max: 63, fuzz: features->tilt_fuzz, flat: 0); |
3570 | input_abs_set_res(dev: input_dev, ABS_TILT_Y, val: 57); |
3571 | } |
3572 | |
3573 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) |
3574 | { |
3575 | struct input_dev *input_dev = wacom_wac->pen_input; |
3576 | |
3577 | input_set_capability(dev: input_dev, EV_REL, REL_WHEEL); |
3578 | |
3579 | wacom_setup_cintiq(wacom_wac); |
3580 | |
3581 | __set_bit(BTN_LEFT, input_dev->keybit); |
3582 | __set_bit(BTN_RIGHT, input_dev->keybit); |
3583 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
3584 | __set_bit(BTN_SIDE, input_dev->keybit); |
3585 | __set_bit(BTN_EXTRA, input_dev->keybit); |
3586 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); |
3587 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); |
3588 | |
3589 | input_set_abs_params(dev: input_dev, ABS_RZ, min: -900, max: 899, fuzz: 0, flat: 0); |
3590 | input_abs_set_res(dev: input_dev, ABS_RZ, val: 287); |
3591 | input_set_abs_params(dev: input_dev, ABS_THROTTLE, min: -1023, max: 1023, fuzz: 0, flat: 0); |
3592 | } |
3593 | |
3594 | void wacom_setup_device_quirks(struct wacom *wacom) |
3595 | { |
3596 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
3597 | struct wacom_features *features = &wacom->wacom_wac.features; |
3598 | |
3599 | /* The pen and pad share the same interface on most devices */ |
3600 | if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || |
3601 | features->type == DTUS || |
3602 | (features->type >= INTUOS3S && features->type <= WACOM_MO)) { |
3603 | if (features->device_type & WACOM_DEVICETYPE_PEN) |
3604 | features->device_type |= WACOM_DEVICETYPE_PAD; |
3605 | } |
3606 | |
3607 | /* touch device found but size is not defined. use default */ |
3608 | if (features->device_type & WACOM_DEVICETYPE_TOUCH && !features->x_max) { |
3609 | features->x_max = 1023; |
3610 | features->y_max = 1023; |
3611 | } |
3612 | |
3613 | /* |
3614 | * Intuos5/Pro and Bamboo 3rd gen have no useful data about its |
3615 | * touch interface in its HID descriptor. If this is the touch |
3616 | * interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the |
3617 | * tablet values. |
3618 | */ |
3619 | if ((features->type >= INTUOS5S && features->type <= INTUOSPL) || |
3620 | (features->type >= INTUOSHT && features->type <= BAMBOO_PT)) { |
3621 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
3622 | if (features->touch_max) |
3623 | features->device_type |= WACOM_DEVICETYPE_TOUCH; |
3624 | if (features->type >= INTUOSHT && features->type <= BAMBOO_PT) |
3625 | features->device_type |= WACOM_DEVICETYPE_PAD; |
3626 | |
3627 | if (features->type == INTUOSHT2) { |
3628 | features->x_max = features->x_max / 10; |
3629 | features->y_max = features->y_max / 10; |
3630 | } |
3631 | else { |
3632 | features->x_max = 4096; |
3633 | features->y_max = 4096; |
3634 | } |
3635 | } |
3636 | else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) { |
3637 | features->device_type |= WACOM_DEVICETYPE_PAD; |
3638 | } |
3639 | } |
3640 | |
3641 | /* |
3642 | * Hack for the Bamboo One: |
3643 | * the device presents a PAD/Touch interface as most Bamboos and even |
3644 | * sends ghosts PAD data on it. However, later, we must disable this |
3645 | * ghost interface, and we can not detect it unless we set it here |
3646 | * to WACOM_DEVICETYPE_PAD or WACOM_DEVICETYPE_TOUCH. |
3647 | */ |
3648 | if (features->type == BAMBOO_PEN && |
3649 | features->pktlen == WACOM_PKGLEN_BBTOUCH3) |
3650 | features->device_type |= WACOM_DEVICETYPE_PAD; |
3651 | |
3652 | /* |
3653 | * Raw Wacom-mode pen and touch events both come from interface |
3654 | * 0, whose HID descriptor has an application usage of 0xFF0D |
3655 | * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back |
3656 | * out through the HID_GENERIC device created for interface 1, |
3657 | * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH. |
3658 | */ |
3659 | if (features->type == BAMBOO_PAD) |
3660 | features->device_type = WACOM_DEVICETYPE_TOUCH; |
3661 | |
3662 | if (features->type == REMOTE) |
3663 | features->device_type = WACOM_DEVICETYPE_PAD; |
3664 | |
3665 | if (features->type == INTUOSP2_BT || |
3666 | features->type == INTUOSP2S_BT) { |
3667 | features->device_type |= WACOM_DEVICETYPE_PEN | |
3668 | WACOM_DEVICETYPE_PAD | |
3669 | WACOM_DEVICETYPE_TOUCH; |
3670 | features->quirks |= WACOM_QUIRK_BATTERY; |
3671 | } |
3672 | |
3673 | if (features->type == INTUOSHT3_BT) { |
3674 | features->device_type |= WACOM_DEVICETYPE_PEN | |
3675 | WACOM_DEVICETYPE_PAD; |
3676 | features->quirks |= WACOM_QUIRK_BATTERY; |
3677 | } |
3678 | |
3679 | switch (features->type) { |
3680 | case PL: |
3681 | case DTU: |
3682 | case DTUS: |
3683 | case DTUSX: |
3684 | case WACOM_21UX2: |
3685 | case WACOM_22HD: |
3686 | case DTK: |
3687 | case WACOM_24HD: |
3688 | case WACOM_27QHD: |
3689 | case CINTIQ_HYBRID: |
3690 | case CINTIQ_COMPANION_2: |
3691 | case CINTIQ: |
3692 | case WACOM_BEE: |
3693 | case WACOM_13HD: |
3694 | case WACOM_24HDT: |
3695 | case WACOM_27QHDT: |
3696 | case TABLETPC: |
3697 | case TABLETPCE: |
3698 | case TABLETPC2FG: |
3699 | case MTSCREEN: |
3700 | case MTTPC: |
3701 | case MTTPC_B: |
3702 | features->device_type |= WACOM_DEVICETYPE_DIRECT; |
3703 | break; |
3704 | } |
3705 | |
3706 | if (wacom->hdev->bus == BUS_BLUETOOTH) |
3707 | features->quirks |= WACOM_QUIRK_BATTERY; |
3708 | |
3709 | /* quirk for bamboo touch with 2 low res touches */ |
3710 | if ((features->type == BAMBOO_PT || features->type == BAMBOO_TOUCH) && |
3711 | features->pktlen == WACOM_PKGLEN_BBTOUCH) { |
3712 | features->x_max <<= 5; |
3713 | features->y_max <<= 5; |
3714 | features->x_fuzz <<= 5; |
3715 | features->y_fuzz <<= 5; |
3716 | features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; |
3717 | } |
3718 | |
3719 | if (features->type == WIRELESS) { |
3720 | if (features->device_type == WACOM_DEVICETYPE_WL_MONITOR) { |
3721 | features->quirks |= WACOM_QUIRK_BATTERY; |
3722 | } |
3723 | } |
3724 | |
3725 | if (features->type == REMOTE) |
3726 | features->device_type |= WACOM_DEVICETYPE_WL_MONITOR; |
3727 | |
3728 | /* HID descriptor for DTK-2451 / DTH-2452 claims to report lots |
3729 | * of things it shouldn't. Lets fix up the damage... |
3730 | */ |
3731 | if (wacom->hdev->product == 0x382 || wacom->hdev->product == 0x37d) { |
3732 | features->quirks &= ~WACOM_QUIRK_TOOLSERIAL; |
3733 | __clear_bit(BTN_TOOL_BRUSH, wacom_wac->pen_input->keybit); |
3734 | __clear_bit(BTN_TOOL_PENCIL, wacom_wac->pen_input->keybit); |
3735 | __clear_bit(BTN_TOOL_AIRBRUSH, wacom_wac->pen_input->keybit); |
3736 | __clear_bit(ABS_Z, wacom_wac->pen_input->absbit); |
3737 | __clear_bit(ABS_DISTANCE, wacom_wac->pen_input->absbit); |
3738 | __clear_bit(ABS_TILT_X, wacom_wac->pen_input->absbit); |
3739 | __clear_bit(ABS_TILT_Y, wacom_wac->pen_input->absbit); |
3740 | __clear_bit(ABS_WHEEL, wacom_wac->pen_input->absbit); |
3741 | __clear_bit(ABS_MISC, wacom_wac->pen_input->absbit); |
3742 | __clear_bit(MSC_SERIAL, wacom_wac->pen_input->mscbit); |
3743 | __clear_bit(EV_MSC, wacom_wac->pen_input->evbit); |
3744 | } |
3745 | } |
3746 | |
3747 | int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, |
3748 | struct wacom_wac *wacom_wac) |
3749 | { |
3750 | struct wacom_features *features = &wacom_wac->features; |
3751 | |
3752 | if (!(features->device_type & WACOM_DEVICETYPE_PEN)) |
3753 | return -ENODEV; |
3754 | |
3755 | if (features->device_type & WACOM_DEVICETYPE_DIRECT) |
3756 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
3757 | else |
3758 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
3759 | |
3760 | if (features->type == HID_GENERIC) |
3761 | /* setup has already been done */ |
3762 | return 0; |
3763 | |
3764 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
3765 | __set_bit(BTN_TOUCH, input_dev->keybit); |
3766 | __set_bit(ABS_MISC, input_dev->absbit); |
3767 | |
3768 | input_set_abs_params(dev: input_dev, ABS_X, min: 0 + features->offset_left, |
3769 | max: features->x_max - features->offset_right, |
3770 | fuzz: features->x_fuzz, flat: 0); |
3771 | input_set_abs_params(dev: input_dev, ABS_Y, min: 0 + features->offset_top, |
3772 | max: features->y_max - features->offset_bottom, |
3773 | fuzz: features->y_fuzz, flat: 0); |
3774 | input_set_abs_params(dev: input_dev, ABS_PRESSURE, min: 0, |
3775 | max: features->pressure_max, fuzz: features->pressure_fuzz, flat: 0); |
3776 | |
3777 | /* penabled devices have fixed resolution for each model */ |
3778 | input_abs_set_res(dev: input_dev, ABS_X, val: features->x_resolution); |
3779 | input_abs_set_res(dev: input_dev, ABS_Y, val: features->y_resolution); |
3780 | |
3781 | switch (features->type) { |
3782 | case GRAPHIRE_BT: |
3783 | __clear_bit(ABS_MISC, input_dev->absbit); |
3784 | fallthrough; |
3785 | |
3786 | case WACOM_MO: |
3787 | case WACOM_G4: |
3788 | input_set_abs_params(dev: input_dev, ABS_DISTANCE, min: 0, |
3789 | max: features->distance_max, |
3790 | fuzz: features->distance_fuzz, flat: 0); |
3791 | fallthrough; |
3792 | |
3793 | case GRAPHIRE: |
3794 | input_set_capability(dev: input_dev, EV_REL, REL_WHEEL); |
3795 | |
3796 | __set_bit(BTN_LEFT, input_dev->keybit); |
3797 | __set_bit(BTN_RIGHT, input_dev->keybit); |
3798 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
3799 | |
3800 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
3801 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
3802 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); |
3803 | __set_bit(BTN_STYLUS, input_dev->keybit); |
3804 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
3805 | break; |
3806 | |
3807 | case WACOM_27QHD: |
3808 | case WACOM_24HD: |
3809 | case DTK: |
3810 | case WACOM_22HD: |
3811 | case WACOM_21UX2: |
3812 | case WACOM_BEE: |
3813 | case CINTIQ: |
3814 | case WACOM_13HD: |
3815 | case CINTIQ_HYBRID: |
3816 | case CINTIQ_COMPANION_2: |
3817 | input_set_abs_params(dev: input_dev, ABS_Z, min: -900, max: 899, fuzz: 0, flat: 0); |
3818 | input_abs_set_res(dev: input_dev, ABS_Z, val: 287); |
3819 | wacom_setup_cintiq(wacom_wac); |
3820 | break; |
3821 | |
3822 | case INTUOS3: |
3823 | case INTUOS3L: |
3824 | case INTUOS3S: |
3825 | case INTUOS4: |
3826 | case INTUOS4WL: |
3827 | case INTUOS4L: |
3828 | case INTUOS4S: |
3829 | input_set_abs_params(dev: input_dev, ABS_Z, min: -900, max: 899, fuzz: 0, flat: 0); |
3830 | input_abs_set_res(dev: input_dev, ABS_Z, val: 287); |
3831 | fallthrough; |
3832 | |
3833 | case INTUOS: |
3834 | wacom_setup_intuos(wacom_wac); |
3835 | break; |
3836 | |
3837 | case INTUOS5: |
3838 | case INTUOS5L: |
3839 | case INTUOSPM: |
3840 | case INTUOSPL: |
3841 | case INTUOS5S: |
3842 | case INTUOSPS: |
3843 | case INTUOSP2_BT: |
3844 | case INTUOSP2S_BT: |
3845 | input_set_abs_params(dev: input_dev, ABS_DISTANCE, min: 0, |
3846 | max: features->distance_max, |
3847 | fuzz: features->distance_fuzz, flat: 0); |
3848 | |
3849 | input_set_abs_params(dev: input_dev, ABS_Z, min: -900, max: 899, fuzz: 0, flat: 0); |
3850 | input_abs_set_res(dev: input_dev, ABS_Z, val: 287); |
3851 | |
3852 | wacom_setup_intuos(wacom_wac); |
3853 | break; |
3854 | |
3855 | case WACOM_24HDT: |
3856 | case WACOM_27QHDT: |
3857 | case MTSCREEN: |
3858 | case MTTPC: |
3859 | case MTTPC_B: |
3860 | case TABLETPC2FG: |
3861 | case TABLETPC: |
3862 | case TABLETPCE: |
3863 | __clear_bit(ABS_MISC, input_dev->absbit); |
3864 | fallthrough; |
3865 | |
3866 | case DTUS: |
3867 | case DTUSX: |
3868 | case PL: |
3869 | case DTU: |
3870 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
3871 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
3872 | __set_bit(BTN_STYLUS, input_dev->keybit); |
3873 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
3874 | break; |
3875 | |
3876 | case PTU: |
3877 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
3878 | fallthrough; |
3879 | |
3880 | case PENPARTNER: |
3881 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
3882 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
3883 | __set_bit(BTN_STYLUS, input_dev->keybit); |
3884 | break; |
3885 | |
3886 | case INTUOSHT: |
3887 | case BAMBOO_PT: |
3888 | case BAMBOO_PEN: |
3889 | case INTUOSHT2: |
3890 | case INTUOSHT3_BT: |
3891 | if (features->type == INTUOSHT2 || |
3892 | features->type == INTUOSHT3_BT) { |
3893 | wacom_setup_basic_pro_pen(wacom_wac); |
3894 | } else { |
3895 | __clear_bit(ABS_MISC, input_dev->absbit); |
3896 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
3897 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
3898 | __set_bit(BTN_STYLUS, input_dev->keybit); |
3899 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
3900 | input_set_abs_params(dev: input_dev, ABS_DISTANCE, min: 0, |
3901 | max: features->distance_max, |
3902 | fuzz: features->distance_fuzz, flat: 0); |
3903 | } |
3904 | break; |
3905 | case BAMBOO_PAD: |
3906 | __clear_bit(ABS_MISC, input_dev->absbit); |
3907 | break; |
3908 | } |
3909 | return 0; |
3910 | } |
3911 | |
3912 | int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, |
3913 | struct wacom_wac *wacom_wac) |
3914 | { |
3915 | struct wacom_features *features = &wacom_wac->features; |
3916 | |
3917 | if (!(features->device_type & WACOM_DEVICETYPE_TOUCH)) |
3918 | return -ENODEV; |
3919 | |
3920 | if (features->device_type & WACOM_DEVICETYPE_DIRECT) |
3921 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
3922 | else |
3923 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
3924 | |
3925 | if (features->type == HID_GENERIC) |
3926 | /* setup has already been done */ |
3927 | return 0; |
3928 | |
3929 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
3930 | __set_bit(BTN_TOUCH, input_dev->keybit); |
3931 | |
3932 | if (features->touch_max == 1) { |
3933 | input_set_abs_params(dev: input_dev, ABS_X, min: 0, |
3934 | max: features->x_max, fuzz: features->x_fuzz, flat: 0); |
3935 | input_set_abs_params(dev: input_dev, ABS_Y, min: 0, |
3936 | max: features->y_max, fuzz: features->y_fuzz, flat: 0); |
3937 | input_abs_set_res(dev: input_dev, ABS_X, |
3938 | val: features->x_resolution); |
3939 | input_abs_set_res(dev: input_dev, ABS_Y, |
3940 | val: features->y_resolution); |
3941 | } |
3942 | else if (features->touch_max > 1) { |
3943 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_X, min: 0, |
3944 | max: features->x_max, fuzz: features->x_fuzz, flat: 0); |
3945 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_Y, min: 0, |
3946 | max: features->y_max, fuzz: features->y_fuzz, flat: 0); |
3947 | input_abs_set_res(dev: input_dev, ABS_MT_POSITION_X, |
3948 | val: features->x_resolution); |
3949 | input_abs_set_res(dev: input_dev, ABS_MT_POSITION_Y, |
3950 | val: features->y_resolution); |
3951 | } |
3952 | |
3953 | switch (features->type) { |
3954 | case INTUOSP2_BT: |
3955 | case INTUOSP2S_BT: |
3956 | input_dev->evbit[0] |= BIT_MASK(EV_SW); |
3957 | __set_bit(SW_MUTE_DEVICE, input_dev->swbit); |
3958 | |
3959 | if (wacom_wac->shared->touch->product == 0x361) { |
3960 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_X, |
3961 | min: 0, max: 12440, fuzz: 4, flat: 0); |
3962 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_Y, |
3963 | min: 0, max: 8640, fuzz: 4, flat: 0); |
3964 | } |
3965 | else if (wacom_wac->shared->touch->product == 0x360) { |
3966 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_X, |
3967 | min: 0, max: 8960, fuzz: 4, flat: 0); |
3968 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_Y, |
3969 | min: 0, max: 5920, fuzz: 4, flat: 0); |
3970 | } |
3971 | else if (wacom_wac->shared->touch->product == 0x393) { |
3972 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_X, |
3973 | min: 0, max: 6400, fuzz: 4, flat: 0); |
3974 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_Y, |
3975 | min: 0, max: 4000, fuzz: 4, flat: 0); |
3976 | } |
3977 | input_abs_set_res(dev: input_dev, ABS_MT_POSITION_X, val: 40); |
3978 | input_abs_set_res(dev: input_dev, ABS_MT_POSITION_Y, val: 40); |
3979 | |
3980 | fallthrough; |
3981 | |
3982 | case INTUOS5: |
3983 | case INTUOS5L: |
3984 | case INTUOSPM: |
3985 | case INTUOSPL: |
3986 | case INTUOS5S: |
3987 | case INTUOSPS: |
3988 | input_set_abs_params(dev: input_dev, ABS_MT_TOUCH_MAJOR, min: 0, max: features->x_max, fuzz: 0, flat: 0); |
3989 | input_set_abs_params(dev: input_dev, ABS_MT_TOUCH_MINOR, min: 0, max: features->y_max, fuzz: 0, flat: 0); |
3990 | input_mt_init_slots(dev: input_dev, num_slots: features->touch_max, INPUT_MT_POINTER); |
3991 | break; |
3992 | |
3993 | case WACOM_24HDT: |
3994 | input_set_abs_params(dev: input_dev, ABS_MT_TOUCH_MAJOR, min: 0, max: features->x_max, fuzz: 0, flat: 0); |
3995 | input_set_abs_params(dev: input_dev, ABS_MT_WIDTH_MAJOR, min: 0, max: features->x_max, fuzz: 0, flat: 0); |
3996 | input_set_abs_params(dev: input_dev, ABS_MT_WIDTH_MINOR, min: 0, max: features->y_max, fuzz: 0, flat: 0); |
3997 | input_set_abs_params(dev: input_dev, ABS_MT_ORIENTATION, min: 0, max: 1, fuzz: 0, flat: 0); |
3998 | fallthrough; |
3999 | |
4000 | case WACOM_27QHDT: |
4001 | if (wacom_wac->shared->touch->product == 0x32C || |
4002 | wacom_wac->shared->touch->product == 0xF6) { |
4003 | input_dev->evbit[0] |= BIT_MASK(EV_SW); |
4004 | __set_bit(SW_MUTE_DEVICE, input_dev->swbit); |
4005 | wacom_wac->has_mute_touch_switch = true; |
4006 | wacom_wac->is_soft_touch_switch = true; |
4007 | } |
4008 | fallthrough; |
4009 | |
4010 | case MTSCREEN: |
4011 | case MTTPC: |
4012 | case MTTPC_B: |
4013 | case TABLETPC2FG: |
4014 | input_mt_init_slots(dev: input_dev, num_slots: features->touch_max, INPUT_MT_DIRECT); |
4015 | fallthrough; |
4016 | |
4017 | case TABLETPC: |
4018 | case TABLETPCE: |
4019 | break; |
4020 | |
4021 | case INTUOSHT: |
4022 | case INTUOSHT2: |
4023 | input_dev->evbit[0] |= BIT_MASK(EV_SW); |
4024 | __set_bit(SW_MUTE_DEVICE, input_dev->swbit); |
4025 | fallthrough; |
4026 | |
4027 | case BAMBOO_PT: |
4028 | case BAMBOO_TOUCH: |
4029 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
4030 | input_set_abs_params(dev: input_dev, |
4031 | ABS_MT_TOUCH_MAJOR, |
4032 | min: 0, max: features->x_max, fuzz: 0, flat: 0); |
4033 | input_set_abs_params(dev: input_dev, |
4034 | ABS_MT_TOUCH_MINOR, |
4035 | min: 0, max: features->y_max, fuzz: 0, flat: 0); |
4036 | } |
4037 | input_mt_init_slots(dev: input_dev, num_slots: features->touch_max, INPUT_MT_POINTER); |
4038 | break; |
4039 | |
4040 | case BAMBOO_PAD: |
4041 | input_mt_init_slots(dev: input_dev, num_slots: features->touch_max, |
4042 | INPUT_MT_POINTER); |
4043 | __set_bit(BTN_LEFT, input_dev->keybit); |
4044 | __set_bit(BTN_RIGHT, input_dev->keybit); |
4045 | break; |
4046 | } |
4047 | return 0; |
4048 | } |
4049 | |
4050 | static int wacom_numbered_button_to_key(int n) |
4051 | { |
4052 | if (n < 10) |
4053 | return BTN_0 + n; |
4054 | else if (n < 16) |
4055 | return BTN_A + (n-10); |
4056 | else if (n < 18) |
4057 | return BTN_BASE + (n-16); |
4058 | else |
4059 | return 0; |
4060 | } |
4061 | |
4062 | static void wacom_setup_numbered_buttons(struct input_dev *input_dev, |
4063 | int button_count) |
4064 | { |
4065 | int i; |
4066 | |
4067 | for (i = 0; i < button_count; i++) { |
4068 | int key = wacom_numbered_button_to_key(n: i); |
4069 | |
4070 | if (key) |
4071 | __set_bit(key, input_dev->keybit); |
4072 | } |
4073 | } |
4074 | |
4075 | static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group) |
4076 | { |
4077 | struct wacom_led *led; |
4078 | int i; |
4079 | bool updated = false; |
4080 | |
4081 | /* |
4082 | * 24HD has LED group 1 to the left and LED group 0 to the right. |
4083 | * So group 0 matches the second half of the buttons and thus the mask |
4084 | * needs to be shifted. |
4085 | */ |
4086 | if (group == 0) |
4087 | mask >>= 8; |
4088 | |
4089 | for (i = 0; i < 3; i++) { |
4090 | led = wacom_led_find(wacom, group, id: i); |
4091 | if (!led) { |
4092 | hid_err(wacom->hdev, "can't find LED %d in group %d\n" , |
4093 | i, group); |
4094 | continue; |
4095 | } |
4096 | if (!updated && mask & BIT(i)) { |
4097 | led->held = true; |
4098 | led_trigger_event(trigger: &led->trigger, event: LED_FULL); |
4099 | } else { |
4100 | led->held = false; |
4101 | } |
4102 | } |
4103 | } |
4104 | |
4105 | static bool wacom_is_led_toggled(struct wacom *wacom, int button_count, |
4106 | int mask, int group) |
4107 | { |
4108 | int group_button; |
4109 | |
4110 | /* |
4111 | * 21UX2 has LED group 1 to the left and LED group 0 |
4112 | * to the right. We need to reverse the group to match this |
4113 | * historical behavior. |
4114 | */ |
4115 | if (wacom->wacom_wac.features.type == WACOM_21UX2) |
4116 | group = 1 - group; |
4117 | |
4118 | group_button = group * (button_count/wacom->led.count); |
4119 | |
4120 | if (wacom->wacom_wac.features.type == INTUOSP2_BT) |
4121 | group_button = 8; |
4122 | |
4123 | return mask & (1 << group_button); |
4124 | } |
4125 | |
4126 | static void wacom_update_led(struct wacom *wacom, int button_count, int mask, |
4127 | int group) |
4128 | { |
4129 | struct wacom_led *led, *next_led; |
4130 | int cur; |
4131 | bool pressed; |
4132 | |
4133 | if (wacom->wacom_wac.features.type == WACOM_24HD) |
4134 | return wacom_24hd_update_leds(wacom, mask, group); |
4135 | |
4136 | pressed = wacom_is_led_toggled(wacom, button_count, mask, group); |
4137 | cur = wacom->led.groups[group].select; |
4138 | |
4139 | led = wacom_led_find(wacom, group, id: cur); |
4140 | if (!led) { |
4141 | hid_err(wacom->hdev, "can't find current LED %d in group %d\n" , |
4142 | cur, group); |
4143 | return; |
4144 | } |
4145 | |
4146 | if (!pressed) { |
4147 | led->held = false; |
4148 | return; |
4149 | } |
4150 | |
4151 | if (led->held && pressed) |
4152 | return; |
4153 | |
4154 | next_led = wacom_led_next(wacom, cur: led); |
4155 | if (!next_led) { |
4156 | hid_err(wacom->hdev, "can't find next LED in group %d\n" , |
4157 | group); |
4158 | return; |
4159 | } |
4160 | if (next_led == led) |
4161 | return; |
4162 | |
4163 | next_led->held = true; |
4164 | led_trigger_event(trigger: &next_led->trigger, |
4165 | event: wacom_leds_brightness_get(led: next_led)); |
4166 | } |
4167 | |
4168 | static void wacom_report_numbered_buttons(struct input_dev *input_dev, |
4169 | int button_count, int mask) |
4170 | { |
4171 | struct wacom *wacom = input_get_drvdata(dev: input_dev); |
4172 | int i; |
4173 | |
4174 | for (i = 0; i < wacom->led.count; i++) |
4175 | wacom_update_led(wacom, button_count, mask, group: i); |
4176 | |
4177 | for (i = 0; i < button_count; i++) { |
4178 | int key = wacom_numbered_button_to_key(n: i); |
4179 | |
4180 | if (key) |
4181 | input_report_key(dev: input_dev, code: key, value: mask & (1 << i)); |
4182 | } |
4183 | } |
4184 | |
4185 | int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, |
4186 | struct wacom_wac *wacom_wac) |
4187 | { |
4188 | struct wacom_features *features = &wacom_wac->features; |
4189 | |
4190 | if ((features->type == HID_GENERIC) && features->numbered_buttons > 0) |
4191 | features->device_type |= WACOM_DEVICETYPE_PAD; |
4192 | |
4193 | if (!(features->device_type & WACOM_DEVICETYPE_PAD)) |
4194 | return -ENODEV; |
4195 | |
4196 | if (features->type == REMOTE && input_dev == wacom_wac->pad_input) |
4197 | return -ENODEV; |
4198 | |
4199 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
4200 | |
4201 | /* kept for making legacy xf86-input-wacom working with the wheels */ |
4202 | __set_bit(ABS_MISC, input_dev->absbit); |
4203 | |
4204 | /* kept for making legacy xf86-input-wacom accepting the pad */ |
4205 | if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum || |
4206 | input_dev->absinfo[ABS_X].maximum))) |
4207 | input_set_abs_params(dev: input_dev, ABS_X, min: 0, max: 1, fuzz: 0, flat: 0); |
4208 | if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum || |
4209 | input_dev->absinfo[ABS_Y].maximum))) |
4210 | input_set_abs_params(dev: input_dev, ABS_Y, min: 0, max: 1, fuzz: 0, flat: 0); |
4211 | |
4212 | /* kept for making udev and libwacom accepting the pad */ |
4213 | __set_bit(BTN_STYLUS, input_dev->keybit); |
4214 | |
4215 | wacom_setup_numbered_buttons(input_dev, button_count: features->numbered_buttons); |
4216 | |
4217 | switch (features->type) { |
4218 | |
4219 | case CINTIQ_HYBRID: |
4220 | case CINTIQ_COMPANION_2: |
4221 | case DTK: |
4222 | case DTUS: |
4223 | case GRAPHIRE_BT: |
4224 | break; |
4225 | |
4226 | case WACOM_MO: |
4227 | __set_bit(BTN_BACK, input_dev->keybit); |
4228 | __set_bit(BTN_LEFT, input_dev->keybit); |
4229 | __set_bit(BTN_FORWARD, input_dev->keybit); |
4230 | __set_bit(BTN_RIGHT, input_dev->keybit); |
4231 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4232 | break; |
4233 | |
4234 | case WACOM_G4: |
4235 | __set_bit(BTN_BACK, input_dev->keybit); |
4236 | __set_bit(BTN_FORWARD, input_dev->keybit); |
4237 | input_set_capability(dev: input_dev, EV_REL, REL_WHEEL); |
4238 | break; |
4239 | |
4240 | case WACOM_24HD: |
4241 | __set_bit(KEY_PROG1, input_dev->keybit); |
4242 | __set_bit(KEY_PROG2, input_dev->keybit); |
4243 | __set_bit(KEY_PROG3, input_dev->keybit); |
4244 | |
4245 | __set_bit(KEY_ONSCREEN_KEYBOARD, input_dev->keybit); |
4246 | __set_bit(KEY_INFO, input_dev->keybit); |
4247 | |
4248 | if (!features->oPid) |
4249 | __set_bit(KEY_BUTTONCONFIG, input_dev->keybit); |
4250 | |
4251 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4252 | input_set_abs_params(dev: input_dev, ABS_THROTTLE, min: 0, max: 71, fuzz: 0, flat: 0); |
4253 | break; |
4254 | |
4255 | case WACOM_27QHD: |
4256 | __set_bit(KEY_PROG1, input_dev->keybit); |
4257 | __set_bit(KEY_PROG2, input_dev->keybit); |
4258 | __set_bit(KEY_PROG3, input_dev->keybit); |
4259 | |
4260 | __set_bit(KEY_ONSCREEN_KEYBOARD, input_dev->keybit); |
4261 | __set_bit(KEY_BUTTONCONFIG, input_dev->keybit); |
4262 | |
4263 | if (!features->oPid) |
4264 | __set_bit(KEY_CONTROLPANEL, input_dev->keybit); |
4265 | input_set_abs_params(dev: input_dev, ABS_X, min: -2048, max: 2048, fuzz: 0, flat: 0); |
4266 | input_abs_set_res(dev: input_dev, ABS_X, val: 1024); /* points/g */ |
4267 | input_set_abs_params(dev: input_dev, ABS_Y, min: -2048, max: 2048, fuzz: 0, flat: 0); |
4268 | input_abs_set_res(dev: input_dev, ABS_Y, val: 1024); |
4269 | input_set_abs_params(dev: input_dev, ABS_Z, min: -2048, max: 2048, fuzz: 0, flat: 0); |
4270 | input_abs_set_res(dev: input_dev, ABS_Z, val: 1024); |
4271 | __set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit); |
4272 | break; |
4273 | |
4274 | case WACOM_22HD: |
4275 | __set_bit(KEY_PROG1, input_dev->keybit); |
4276 | __set_bit(KEY_PROG2, input_dev->keybit); |
4277 | __set_bit(KEY_PROG3, input_dev->keybit); |
4278 | |
4279 | __set_bit(KEY_BUTTONCONFIG, input_dev->keybit); |
4280 | __set_bit(KEY_INFO, input_dev->keybit); |
4281 | fallthrough; |
4282 | |
4283 | case WACOM_21UX2: |
4284 | case WACOM_BEE: |
4285 | case CINTIQ: |
4286 | input_set_abs_params(dev: input_dev, ABS_RX, min: 0, max: 4096, fuzz: 0, flat: 0); |
4287 | input_set_abs_params(dev: input_dev, ABS_RY, min: 0, max: 4096, fuzz: 0, flat: 0); |
4288 | break; |
4289 | |
4290 | case WACOM_13HD: |
4291 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4292 | break; |
4293 | |
4294 | case INTUOS3: |
4295 | case INTUOS3L: |
4296 | input_set_abs_params(dev: input_dev, ABS_RY, min: 0, max: 4096, fuzz: 0, flat: 0); |
4297 | fallthrough; |
4298 | |
4299 | case INTUOS3S: |
4300 | input_set_abs_params(dev: input_dev, ABS_RX, min: 0, max: 4096, fuzz: 0, flat: 0); |
4301 | break; |
4302 | |
4303 | case INTUOS5: |
4304 | case INTUOS5L: |
4305 | case INTUOSPM: |
4306 | case INTUOSPL: |
4307 | case INTUOS5S: |
4308 | case INTUOSPS: |
4309 | case INTUOSP2_BT: |
4310 | case INTUOSP2S_BT: |
4311 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4312 | break; |
4313 | |
4314 | case INTUOS4WL: |
4315 | /* |
4316 | * For Bluetooth devices, the udev rule does not work correctly |
4317 | * for pads unless we add a stylus capability, which forces |
4318 | * ID_INPUT_TABLET to be set. |
4319 | */ |
4320 | __set_bit(BTN_STYLUS, input_dev->keybit); |
4321 | fallthrough; |
4322 | |
4323 | case INTUOS4: |
4324 | case INTUOS4L: |
4325 | case INTUOS4S: |
4326 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4327 | break; |
4328 | |
4329 | case INTUOSHT: |
4330 | case BAMBOO_PT: |
4331 | case BAMBOO_TOUCH: |
4332 | case INTUOSHT2: |
4333 | __clear_bit(ABS_MISC, input_dev->absbit); |
4334 | |
4335 | __set_bit(BTN_LEFT, input_dev->keybit); |
4336 | __set_bit(BTN_FORWARD, input_dev->keybit); |
4337 | __set_bit(BTN_BACK, input_dev->keybit); |
4338 | __set_bit(BTN_RIGHT, input_dev->keybit); |
4339 | |
4340 | break; |
4341 | |
4342 | case REMOTE: |
4343 | input_set_capability(dev: input_dev, EV_MSC, MSC_SERIAL); |
4344 | input_set_abs_params(dev: input_dev, ABS_WHEEL, min: 0, max: 71, fuzz: 0, flat: 0); |
4345 | break; |
4346 | |
4347 | case INTUOSHT3_BT: |
4348 | case HID_GENERIC: |
4349 | break; |
4350 | |
4351 | default: |
4352 | /* no pad supported */ |
4353 | return -ENODEV; |
4354 | } |
4355 | return 0; |
4356 | } |
4357 | |
4358 | static const struct wacom_features wacom_features_0x00 = |
4359 | { "Wacom Penpartner" , 5040, 3780, 255, 0, |
4360 | PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; |
4361 | static const struct wacom_features wacom_features_0x10 = |
4362 | { "Wacom Graphire" , 10206, 7422, 511, 63, |
4363 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4364 | static const struct wacom_features wacom_features_0x81 = |
4365 | { "Wacom Graphire BT" , 16704, 12064, 511, 32, |
4366 | GRAPHIRE_BT, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES, 2 }; |
4367 | static const struct wacom_features wacom_features_0x11 = |
4368 | { "Wacom Graphire2 4x5" , 10206, 7422, 511, 63, |
4369 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4370 | static const struct wacom_features wacom_features_0x12 = |
4371 | { "Wacom Graphire2 5x7" , 13918, 10206, 511, 63, |
4372 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4373 | static const struct wacom_features wacom_features_0x13 = |
4374 | { "Wacom Graphire3" , 10208, 7424, 511, 63, |
4375 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4376 | static const struct wacom_features wacom_features_0x14 = |
4377 | { "Wacom Graphire3 6x8" , 16704, 12064, 511, 63, |
4378 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4379 | static const struct wacom_features wacom_features_0x15 = |
4380 | { "Wacom Graphire4 4x5" , 10208, 7424, 511, 63, |
4381 | WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4382 | static const struct wacom_features wacom_features_0x16 = |
4383 | { "Wacom Graphire4 6x8" , 16704, 12064, 511, 63, |
4384 | WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4385 | static const struct wacom_features wacom_features_0x17 = |
4386 | { "Wacom BambooFun 4x5" , 14760, 9225, 511, 63, |
4387 | WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4388 | static const struct wacom_features wacom_features_0x18 = |
4389 | { "Wacom BambooFun 6x8" , 21648, 13530, 511, 63, |
4390 | WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4391 | static const struct wacom_features wacom_features_0x19 = |
4392 | { "Wacom Bamboo1 Medium" , 16704, 12064, 511, 63, |
4393 | GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; |
4394 | static const struct wacom_features wacom_features_0x60 = |
4395 | { "Wacom Volito" , 5104, 3712, 511, 63, |
4396 | GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; |
4397 | static const struct wacom_features wacom_features_0x61 = |
4398 | { "Wacom PenStation2" , 3250, 2320, 255, 63, |
4399 | GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; |
4400 | static const struct wacom_features wacom_features_0x62 = |
4401 | { "Wacom Volito2 4x5" , 5104, 3712, 511, 63, |
4402 | GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; |
4403 | static const struct wacom_features wacom_features_0x63 = |
4404 | { "Wacom Volito2 2x3" , 3248, 2320, 511, 63, |
4405 | GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; |
4406 | static const struct wacom_features wacom_features_0x64 = |
4407 | { "Wacom PenPartner2" , 3250, 2320, 511, 63, |
4408 | GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; |
4409 | static const struct wacom_features wacom_features_0x65 = |
4410 | { "Wacom Bamboo" , 14760, 9225, 511, 63, |
4411 | WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4412 | static const struct wacom_features wacom_features_0x69 = |
4413 | { "Wacom Bamboo1" , 5104, 3712, 511, 63, |
4414 | GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; |
4415 | static const struct wacom_features wacom_features_0x6A = |
4416 | { "Wacom Bamboo1 4x6" , 14760, 9225, 1023, 63, |
4417 | GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4418 | static const struct wacom_features wacom_features_0x6B = |
4419 | { "Wacom Bamboo1 5x8" , 21648, 13530, 1023, 63, |
4420 | GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4421 | static const struct wacom_features wacom_features_0x20 = |
4422 | { "Wacom Intuos 4x5" , 12700, 10600, 1023, 31, |
4423 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4424 | static const struct wacom_features wacom_features_0x21 = |
4425 | { "Wacom Intuos 6x8" , 20320, 16240, 1023, 31, |
4426 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4427 | static const struct wacom_features wacom_features_0x22 = |
4428 | { "Wacom Intuos 9x12" , 30480, 24060, 1023, 31, |
4429 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4430 | static const struct wacom_features wacom_features_0x23 = |
4431 | { "Wacom Intuos 12x12" , 30480, 31680, 1023, 31, |
4432 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4433 | static const struct wacom_features wacom_features_0x24 = |
4434 | { "Wacom Intuos 12x18" , 45720, 31680, 1023, 31, |
4435 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4436 | static const struct wacom_features wacom_features_0x30 = |
4437 | { "Wacom PL400" , 5408, 4056, 255, 0, |
4438 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4439 | static const struct wacom_features wacom_features_0x31 = |
4440 | { "Wacom PL500" , 6144, 4608, 255, 0, |
4441 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4442 | static const struct wacom_features wacom_features_0x32 = |
4443 | { "Wacom PL600" , 6126, 4604, 255, 0, |
4444 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4445 | static const struct wacom_features wacom_features_0x33 = |
4446 | { "Wacom PL600SX" , 6260, 5016, 255, 0, |
4447 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4448 | static const struct wacom_features wacom_features_0x34 = |
4449 | { "Wacom PL550" , 6144, 4608, 511, 0, |
4450 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4451 | static const struct wacom_features wacom_features_0x35 = |
4452 | { "Wacom PL800" , 7220, 5780, 511, 0, |
4453 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4454 | static const struct wacom_features wacom_features_0x37 = |
4455 | { "Wacom PL700" , 6758, 5406, 511, 0, |
4456 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4457 | static const struct wacom_features wacom_features_0x38 = |
4458 | { "Wacom PL510" , 6282, 4762, 511, 0, |
4459 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4460 | static const struct wacom_features wacom_features_0x39 = |
4461 | { "Wacom DTU710" , 34080, 27660, 511, 0, |
4462 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4463 | static const struct wacom_features wacom_features_0xC4 = |
4464 | { "Wacom DTF521" , 6282, 4762, 511, 0, |
4465 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4466 | static const struct wacom_features wacom_features_0xC0 = |
4467 | { "Wacom DTF720" , 6858, 5506, 511, 0, |
4468 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4469 | static const struct wacom_features wacom_features_0xC2 = |
4470 | { "Wacom DTF720a" , 6858, 5506, 511, 0, |
4471 | PL, WACOM_PL_RES, WACOM_PL_RES }; |
4472 | static const struct wacom_features wacom_features_0x03 = |
4473 | { "Wacom Cintiq Partner" , 20480, 15360, 511, 0, |
4474 | PTU, WACOM_PL_RES, WACOM_PL_RES }; |
4475 | static const struct wacom_features wacom_features_0x41 = |
4476 | { "Wacom Intuos2 4x5" , 12700, 10600, 1023, 31, |
4477 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4478 | static const struct wacom_features wacom_features_0x42 = |
4479 | { "Wacom Intuos2 6x8" , 20320, 16240, 1023, 31, |
4480 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4481 | static const struct wacom_features wacom_features_0x43 = |
4482 | { "Wacom Intuos2 9x12" , 30480, 24060, 1023, 31, |
4483 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4484 | static const struct wacom_features wacom_features_0x44 = |
4485 | { "Wacom Intuos2 12x12" , 30480, 31680, 1023, 31, |
4486 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4487 | static const struct wacom_features wacom_features_0x45 = |
4488 | { "Wacom Intuos2 12x18" , 45720, 31680, 1023, 31, |
4489 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4490 | static const struct wacom_features wacom_features_0xB0 = |
4491 | { "Wacom Intuos3 4x5" , 25400, 20320, 1023, 63, |
4492 | INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 }; |
4493 | static const struct wacom_features wacom_features_0xB1 = |
4494 | { "Wacom Intuos3 6x8" , 40640, 30480, 1023, 63, |
4495 | INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4496 | static const struct wacom_features wacom_features_0xB2 = |
4497 | { "Wacom Intuos3 9x12" , 60960, 45720, 1023, 63, |
4498 | INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4499 | static const struct wacom_features wacom_features_0xB3 = |
4500 | { "Wacom Intuos3 12x12" , 60960, 60960, 1023, 63, |
4501 | INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4502 | static const struct wacom_features wacom_features_0xB4 = |
4503 | { "Wacom Intuos3 12x19" , 97536, 60960, 1023, 63, |
4504 | INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4505 | static const struct wacom_features wacom_features_0xB5 = |
4506 | { "Wacom Intuos3 6x11" , 54204, 31750, 1023, 63, |
4507 | INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4508 | static const struct wacom_features wacom_features_0xB7 = |
4509 | { "Wacom Intuos3 4x6" , 31496, 19685, 1023, 63, |
4510 | INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 4 }; |
4511 | static const struct wacom_features wacom_features_0xB8 = |
4512 | { "Wacom Intuos4 4x6" , 31496, 19685, 2047, 63, |
4513 | INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 }; |
4514 | static const struct wacom_features wacom_features_0xB9 = |
4515 | { "Wacom Intuos4 6x9" , 44704, 27940, 2047, 63, |
4516 | INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4517 | static const struct wacom_features wacom_features_0xBA = |
4518 | { "Wacom Intuos4 8x13" , 65024, 40640, 2047, 63, |
4519 | INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4520 | static const struct wacom_features wacom_features_0xBB = |
4521 | { "Wacom Intuos4 12x19" , 97536, 60960, 2047, 63, |
4522 | INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4523 | static const struct wacom_features wacom_features_0xBC = |
4524 | { "Wacom Intuos4 WL" , 40640, 25400, 2047, 63, |
4525 | INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4526 | static const struct wacom_features wacom_features_0xBD = |
4527 | { "Wacom Intuos4 WL" , 40640, 25400, 2047, 63, |
4528 | INTUOS4WL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4529 | static const struct wacom_features wacom_features_0x26 = |
4530 | { "Wacom Intuos5 touch S" , 31496, 19685, 2047, 63, |
4531 | INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16 }; |
4532 | static const struct wacom_features wacom_features_0x27 = |
4533 | { "Wacom Intuos5 touch M" , 44704, 27940, 2047, 63, |
4534 | INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 }; |
4535 | static const struct wacom_features wacom_features_0x28 = |
4536 | { "Wacom Intuos5 touch L" , 65024, 40640, 2047, 63, |
4537 | INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16 }; |
4538 | static const struct wacom_features wacom_features_0x29 = |
4539 | { "Wacom Intuos5 S" , 31496, 19685, 2047, 63, |
4540 | INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7 }; |
4541 | static const struct wacom_features wacom_features_0x2A = |
4542 | { "Wacom Intuos5 M" , 44704, 27940, 2047, 63, |
4543 | INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9 }; |
4544 | static const struct wacom_features wacom_features_0x314 = |
4545 | { "Wacom Intuos Pro S" , 31496, 19685, 2047, 63, |
4546 | INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16, |
4547 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4548 | static const struct wacom_features wacom_features_0x315 = |
4549 | { "Wacom Intuos Pro M" , 44704, 27940, 2047, 63, |
4550 | INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, |
4551 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4552 | static const struct wacom_features wacom_features_0x317 = |
4553 | { "Wacom Intuos Pro L" , 65024, 40640, 2047, 63, |
4554 | INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16, |
4555 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4556 | static const struct wacom_features wacom_features_0xF4 = |
4557 | { "Wacom Cintiq 24HD" , 104480, 65600, 2047, 63, |
4558 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, |
4559 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4560 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4561 | static const struct wacom_features wacom_features_0xF8 = |
4562 | { "Wacom Cintiq 24HD touch" , 104480, 65600, 2047, 63, /* Pen */ |
4563 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16, |
4564 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4565 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4566 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; |
4567 | static const struct wacom_features wacom_features_0xF6 = |
4568 | { "Wacom Cintiq 24HD touch" , .type = WACOM_24HDT, /* Touch */ |
4569 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, |
4570 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4571 | static const struct wacom_features wacom_features_0x32A = |
4572 | { "Wacom Cintiq 27QHD" , 120140, 67920, 2047, 63, |
4573 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, |
4574 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4575 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4576 | static const struct wacom_features wacom_features_0x32B = |
4577 | { "Wacom Cintiq 27QHD touch" , 120140, 67920, 2047, 63, |
4578 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0, |
4579 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4580 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4581 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C }; |
4582 | static const struct wacom_features wacom_features_0x32C = |
4583 | { "Wacom Cintiq 27QHD touch" , .type = WACOM_27QHDT, |
4584 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 }; |
4585 | static const struct wacom_features wacom_features_0x3F = |
4586 | { "Wacom Cintiq 21UX" , 87200, 65600, 1023, 63, |
4587 | CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 8 }; |
4588 | static const struct wacom_features wacom_features_0xC5 = |
4589 | { "Wacom Cintiq 20WSX" , 86680, 54180, 1023, 63, |
4590 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 }; |
4591 | static const struct wacom_features wacom_features_0xC6 = |
4592 | { "Wacom Cintiq 12WX" , 53020, 33440, 1023, 63, |
4593 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 }; |
4594 | static const struct wacom_features wacom_features_0x304 = |
4595 | { "Wacom Cintiq 13HD" , 59552, 33848, 1023, 63, |
4596 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
4597 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4598 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4599 | static const struct wacom_features wacom_features_0x333 = |
4600 | { "Wacom Cintiq 13HD touch" , 59552, 33848, 2047, 63, |
4601 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
4602 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4603 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4604 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 }; |
4605 | static const struct wacom_features wacom_features_0x335 = |
4606 | { "Wacom Cintiq 13HD touch" , .type = WACOM_24HDT, /* Touch */ |
4607 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x333, .touch_max = 10, |
4608 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4609 | static const struct wacom_features wacom_features_0xC7 = |
4610 | { "Wacom DTU1931" , 37832, 30305, 511, 0, |
4611 | PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4612 | static const struct wacom_features wacom_features_0xCE = |
4613 | { "Wacom DTU2231" , 47864, 27011, 511, 0, |
4614 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
4615 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBMOUSE }; |
4616 | static const struct wacom_features wacom_features_0xF0 = |
4617 | { "Wacom DTU1631" , 34623, 19553, 511, 0, |
4618 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4619 | static const struct wacom_features wacom_features_0xFB = |
4620 | { "Wacom DTU1031" , 22096, 13960, 511, 0, |
4621 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
4622 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, |
4623 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
4624 | static const struct wacom_features wacom_features_0x32F = |
4625 | { "Wacom DTU1031X" , 22672, 12928, 511, 0, |
4626 | DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0, |
4627 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, |
4628 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
4629 | static const struct wacom_features wacom_features_0x336 = |
4630 | { "Wacom DTU1141" , 23672, 13403, 1023, 0, |
4631 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
4632 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, |
4633 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
4634 | static const struct wacom_features wacom_features_0x57 = |
4635 | { "Wacom DTK2241" , 95840, 54260, 2047, 63, |
4636 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, |
4637 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4638 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4639 | static const struct wacom_features wacom_features_0x59 = /* Pen */ |
4640 | { "Wacom DTH2242" , 95840, 54260, 2047, 63, |
4641 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6, |
4642 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4643 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4644 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; |
4645 | static const struct wacom_features wacom_features_0x5D = /* Touch */ |
4646 | { "Wacom DTH2242" , .type = WACOM_24HDT, |
4647 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, |
4648 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4649 | static const struct wacom_features wacom_features_0xCC = |
4650 | { "Wacom Cintiq 21UX2" , 87200, 65600, 2047, 63, |
4651 | WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
4652 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4653 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4654 | static const struct wacom_features wacom_features_0xFA = |
4655 | { "Wacom Cintiq 22HD" , 95840, 54260, 2047, 63, |
4656 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
4657 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4658 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; |
4659 | static const struct wacom_features wacom_features_0x5B = |
4660 | { "Wacom Cintiq 22HDT" , 95840, 54260, 2047, 63, |
4661 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18, |
4662 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4663 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4664 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; |
4665 | static const struct wacom_features wacom_features_0x5E = |
4666 | { "Wacom Cintiq 22HDT" , .type = WACOM_24HDT, |
4667 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5b, .touch_max = 10, |
4668 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4669 | static const struct wacom_features wacom_features_0x90 = |
4670 | { "Wacom ISDv4 90" , 26202, 16325, 255, 0, |
4671 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */ |
4672 | static const struct wacom_features wacom_features_0x93 = |
4673 | { "Wacom ISDv4 93" , 26202, 16325, 255, 0, |
4674 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 }; |
4675 | static const struct wacom_features wacom_features_0x97 = |
4676 | { "Wacom ISDv4 97" , 26202, 16325, 511, 0, |
4677 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */ |
4678 | static const struct wacom_features wacom_features_0x9A = |
4679 | { "Wacom ISDv4 9A" , 26202, 16325, 255, 0, |
4680 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 }; |
4681 | static const struct wacom_features wacom_features_0x9F = |
4682 | { "Wacom ISDv4 9F" , 26202, 16325, 255, 0, |
4683 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 }; |
4684 | static const struct wacom_features wacom_features_0xE2 = |
4685 | { "Wacom ISDv4 E2" , 26202, 16325, 255, 0, |
4686 | TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4687 | static const struct wacom_features wacom_features_0xE3 = |
4688 | { "Wacom ISDv4 E3" , 26202, 16325, 255, 0, |
4689 | TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4690 | static const struct wacom_features wacom_features_0xE5 = |
4691 | { "Wacom ISDv4 E5" , 26202, 16325, 255, 0, |
4692 | MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4693 | static const struct wacom_features wacom_features_0xE6 = |
4694 | { "Wacom ISDv4 E6" , 27760, 15694, 255, 0, |
4695 | TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4696 | static const struct wacom_features wacom_features_0xEC = |
4697 | { "Wacom ISDv4 EC" , 25710, 14500, 255, 0, |
4698 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */ |
4699 | static const struct wacom_features wacom_features_0xED = |
4700 | { "Wacom ISDv4 ED" , 26202, 16325, 255, 0, |
4701 | TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 }; |
4702 | static const struct wacom_features wacom_features_0xEF = |
4703 | { "Wacom ISDv4 EF" , 26202, 16325, 255, 0, |
4704 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */ |
4705 | static const struct wacom_features wacom_features_0x100 = |
4706 | { "Wacom ISDv4 100" , 26202, 16325, 255, 0, |
4707 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4708 | static const struct wacom_features wacom_features_0x101 = |
4709 | { "Wacom ISDv4 101" , 26202, 16325, 255, 0, |
4710 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4711 | static const struct wacom_features wacom_features_0x10D = |
4712 | { "Wacom ISDv4 10D" , 26202, 16325, 255, 0, |
4713 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4714 | static const struct wacom_features wacom_features_0x10E = |
4715 | { "Wacom ISDv4 10E" , 27760, 15694, 255, 0, |
4716 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4717 | static const struct wacom_features wacom_features_0x10F = |
4718 | { "Wacom ISDv4 10F" , 27760, 15694, 255, 0, |
4719 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4720 | static const struct wacom_features wacom_features_0x116 = |
4721 | { "Wacom ISDv4 116" , 26202, 16325, 255, 0, |
4722 | TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 }; |
4723 | static const struct wacom_features wacom_features_0x12C = |
4724 | { "Wacom ISDv4 12C" , 27848, 15752, 2047, 0, |
4725 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */ |
4726 | static const struct wacom_features wacom_features_0x4001 = |
4727 | { "Wacom ISDv4 4001" , 26202, 16325, 255, 0, |
4728 | MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4729 | static const struct wacom_features wacom_features_0x4004 = |
4730 | { "Wacom ISDv4 4004" , 11060, 6220, 255, 0, |
4731 | MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4732 | static const struct wacom_features wacom_features_0x5000 = |
4733 | { "Wacom ISDv4 5000" , 27848, 15752, 1023, 0, |
4734 | MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4735 | static const struct wacom_features wacom_features_0x5002 = |
4736 | { "Wacom ISDv4 5002" , 29576, 16724, 1023, 0, |
4737 | MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4738 | static const struct wacom_features wacom_features_0x47 = |
4739 | { "Wacom Intuos2 6x8" , 20320, 16240, 1023, 31, |
4740 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4741 | static const struct wacom_features wacom_features_0x84 = |
4742 | { "Wacom Wireless Receiver" , .type = WIRELESS, .touch_max = 16 }; |
4743 | static const struct wacom_features wacom_features_0xD0 = |
4744 | { "Wacom Bamboo 2FG" , 14720, 9200, 1023, 31, |
4745 | BAMBOO_TOUCH, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4746 | static const struct wacom_features wacom_features_0xD1 = |
4747 | { "Wacom Bamboo 2FG 4x5" , 14720, 9200, 1023, 31, |
4748 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4749 | static const struct wacom_features wacom_features_0xD2 = |
4750 | { "Wacom Bamboo Craft" , 14720, 9200, 1023, 31, |
4751 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4752 | static const struct wacom_features wacom_features_0xD3 = |
4753 | { "Wacom Bamboo 2FG 6x8" , 21648, 13700, 1023, 31, |
4754 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4755 | static const struct wacom_features wacom_features_0xD4 = |
4756 | { "Wacom Bamboo Pen" , 14720, 9200, 1023, 31, |
4757 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4758 | static const struct wacom_features wacom_features_0xD5 = |
4759 | { "Wacom Bamboo Pen 6x8" , 21648, 13700, 1023, 31, |
4760 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4761 | static const struct wacom_features wacom_features_0xD6 = |
4762 | { "Wacom BambooPT 2FG 4x5" , 14720, 9200, 1023, 31, |
4763 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4764 | static const struct wacom_features wacom_features_0xD7 = |
4765 | { "Wacom BambooPT 2FG Small" , 14720, 9200, 1023, 31, |
4766 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4767 | static const struct wacom_features wacom_features_0xD8 = |
4768 | { "Wacom Bamboo Comic 2FG" , 21648, 13700, 1023, 31, |
4769 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4770 | static const struct wacom_features wacom_features_0xDA = |
4771 | { "Wacom Bamboo 2FG 4x5 SE" , 14720, 9200, 1023, 31, |
4772 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4773 | static const struct wacom_features wacom_features_0xDB = |
4774 | { "Wacom Bamboo 2FG 6x8 SE" , 21648, 13700, 1023, 31, |
4775 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
4776 | static const struct wacom_features wacom_features_0xDD = |
4777 | { "Wacom Bamboo Connect" , 14720, 9200, 1023, 31, |
4778 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4779 | static const struct wacom_features wacom_features_0xDE = |
4780 | { "Wacom Bamboo 16FG 4x5" , 14720, 9200, 1023, 31, |
4781 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; |
4782 | static const struct wacom_features wacom_features_0xDF = |
4783 | { "Wacom Bamboo 16FG 6x8" , 21648, 13700, 1023, 31, |
4784 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; |
4785 | static const struct wacom_features wacom_features_0x300 = |
4786 | { "Wacom Bamboo One S" , 14720, 9225, 1023, 31, |
4787 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4788 | static const struct wacom_features wacom_features_0x301 = |
4789 | { "Wacom Bamboo One M" , 21648, 13530, 1023, 31, |
4790 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4791 | static const struct wacom_features wacom_features_0x302 = |
4792 | { "Wacom Intuos PT S" , 15200, 9500, 1023, 31, |
4793 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
4794 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4795 | static const struct wacom_features wacom_features_0x303 = |
4796 | { "Wacom Intuos PT M" , 21600, 13500, 1023, 31, |
4797 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
4798 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4799 | static const struct wacom_features wacom_features_0x30E = |
4800 | { "Wacom Intuos S" , 15200, 9500, 1023, 31, |
4801 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
4802 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4803 | static const struct wacom_features wacom_features_0x6004 = |
4804 | { "ISD-V4" , 12800, 8000, 255, 0, |
4805 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4806 | static const struct wacom_features wacom_features_0x307 = |
4807 | { "Wacom ISDv5 307" , 59552, 33848, 2047, 63, |
4808 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
4809 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4810 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4811 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; |
4812 | static const struct wacom_features wacom_features_0x309 = |
4813 | { "Wacom ISDv5 309" , .type = WACOM_24HDT, /* Touch */ |
4814 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, |
4815 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4816 | static const struct wacom_features wacom_features_0x30A = |
4817 | { "Wacom ISDv5 30A" , 59552, 33848, 2047, 63, |
4818 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, |
4819 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4820 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4821 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; |
4822 | static const struct wacom_features wacom_features_0x30C = |
4823 | { "Wacom ISDv5 30C" , .type = WACOM_24HDT, /* Touch */ |
4824 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10, |
4825 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4826 | static const struct wacom_features wacom_features_0x318 = |
4827 | { "Wacom USB Bamboo PAD" , 4095, 4095, /* Touch */ |
4828 | .type = BAMBOO_PAD, 35, 48, .touch_max = 4 }; |
4829 | static const struct wacom_features wacom_features_0x319 = |
4830 | { "Wacom Wireless Bamboo PAD" , 4095, 4095, /* Touch */ |
4831 | .type = BAMBOO_PAD, 35, 48, .touch_max = 4 }; |
4832 | static const struct wacom_features wacom_features_0x325 = |
4833 | { "Wacom ISDv5 325" , 59552, 33848, 2047, 63, |
4834 | CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11, |
4835 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4836 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, |
4837 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 }; |
4838 | static const struct wacom_features wacom_features_0x326 = /* Touch */ |
4839 | { "Wacom ISDv5 326" , .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM, |
4840 | .oPid = 0x325 }; |
4841 | static const struct wacom_features wacom_features_0x323 = |
4842 | { "Wacom Intuos P M" , 21600, 13500, 1023, 31, |
4843 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
4844 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4845 | static const struct wacom_features wacom_features_0x331 = |
4846 | { "Wacom Express Key Remote" , .type = REMOTE, |
4847 | .numbered_buttons = 18, .check_for_hid_type = true, |
4848 | .hid_type = HID_TYPE_USBNONE }; |
4849 | static const struct wacom_features wacom_features_0x33B = |
4850 | { "Wacom Intuos S 2" , 15200, 9500, 2047, 63, |
4851 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
4852 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4853 | static const struct wacom_features wacom_features_0x33C = |
4854 | { "Wacom Intuos PT S 2" , 15200, 9500, 2047, 63, |
4855 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
4856 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4857 | static const struct wacom_features wacom_features_0x33D = |
4858 | { "Wacom Intuos P M 2" , 21600, 13500, 2047, 63, |
4859 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
4860 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4861 | static const struct wacom_features wacom_features_0x33E = |
4862 | { "Wacom Intuos PT M 2" , 21600, 13500, 2047, 63, |
4863 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, |
4864 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
4865 | static const struct wacom_features wacom_features_0x343 = |
4866 | { "Wacom DTK1651" , 34816, 19759, 1023, 0, |
4867 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4, |
4868 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET, |
4869 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; |
4870 | static const struct wacom_features wacom_features_0x360 = |
4871 | { "Wacom Intuos Pro M" , 44800, 29600, 8191, 63, |
4872 | INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 }; |
4873 | static const struct wacom_features wacom_features_0x361 = |
4874 | { "Wacom Intuos Pro L" , 62200, 43200, 8191, 63, |
4875 | INTUOSP2_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 10 }; |
4876 | static const struct wacom_features wacom_features_0x377 = |
4877 | { "Wacom Intuos BT S" , 15200, 9500, 4095, 63, |
4878 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; |
4879 | static const struct wacom_features wacom_features_0x379 = |
4880 | { "Wacom Intuos BT M" , 21600, 13500, 4095, 63, |
4881 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; |
4882 | static const struct wacom_features wacom_features_0x37A = |
4883 | { "Wacom One by Wacom S" , 15200, 9500, 2047, 63, |
4884 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4885 | static const struct wacom_features wacom_features_0x37B = |
4886 | { "Wacom One by Wacom M" , 21600, 13500, 2047, 63, |
4887 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
4888 | static const struct wacom_features wacom_features_0x393 = |
4889 | { "Wacom Intuos Pro S" , 31920, 19950, 8191, 63, |
4890 | INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, |
4891 | .touch_max = 10 }; |
4892 | static const struct wacom_features wacom_features_0x3c6 = |
4893 | { "Wacom Intuos BT S" , 15200, 9500, 4095, 63, |
4894 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; |
4895 | static const struct wacom_features wacom_features_0x3c8 = |
4896 | { "Wacom Intuos BT M" , 21600, 13500, 4095, 63, |
4897 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; |
4898 | static const struct wacom_features wacom_features_0x3dd = |
4899 | { "Wacom Intuos Pro S" , 31920, 19950, 8191, 63, |
4900 | INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, |
4901 | .touch_max = 10 }; |
4902 | |
4903 | static const struct wacom_features wacom_features_HID_ANY_ID = |
4904 | { "Wacom HID" , .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; |
4905 | |
4906 | static const struct wacom_features wacom_features_0x94 = |
4907 | { "Wacom Bootloader" , .type = BOOTLOADER }; |
4908 | |
4909 | #define USB_DEVICE_WACOM(prod) \ |
4910 | HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ |
4911 | .driver_data = (kernel_ulong_t)&wacom_features_##prod |
4912 | |
4913 | #define BT_DEVICE_WACOM(prod) \ |
4914 | HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ |
4915 | .driver_data = (kernel_ulong_t)&wacom_features_##prod |
4916 | |
4917 | #define I2C_DEVICE_WACOM(prod) \ |
4918 | HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ |
4919 | .driver_data = (kernel_ulong_t)&wacom_features_##prod |
4920 | |
4921 | #define USB_DEVICE_LENOVO(prod) \ |
4922 | HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ |
4923 | .driver_data = (kernel_ulong_t)&wacom_features_##prod |
4924 | |
4925 | const struct hid_device_id wacom_ids[] = { |
4926 | { USB_DEVICE_WACOM(0x00) }, |
4927 | { USB_DEVICE_WACOM(0x03) }, |
4928 | { USB_DEVICE_WACOM(0x10) }, |
4929 | { USB_DEVICE_WACOM(0x11) }, |
4930 | { USB_DEVICE_WACOM(0x12) }, |
4931 | { USB_DEVICE_WACOM(0x13) }, |
4932 | { USB_DEVICE_WACOM(0x14) }, |
4933 | { USB_DEVICE_WACOM(0x15) }, |
4934 | { USB_DEVICE_WACOM(0x16) }, |
4935 | { USB_DEVICE_WACOM(0x17) }, |
4936 | { USB_DEVICE_WACOM(0x18) }, |
4937 | { USB_DEVICE_WACOM(0x19) }, |
4938 | { USB_DEVICE_WACOM(0x20) }, |
4939 | { USB_DEVICE_WACOM(0x21) }, |
4940 | { USB_DEVICE_WACOM(0x22) }, |
4941 | { USB_DEVICE_WACOM(0x23) }, |
4942 | { USB_DEVICE_WACOM(0x24) }, |
4943 | { USB_DEVICE_WACOM(0x26) }, |
4944 | { USB_DEVICE_WACOM(0x27) }, |
4945 | { USB_DEVICE_WACOM(0x28) }, |
4946 | { USB_DEVICE_WACOM(0x29) }, |
4947 | { USB_DEVICE_WACOM(0x2A) }, |
4948 | { USB_DEVICE_WACOM(0x30) }, |
4949 | { USB_DEVICE_WACOM(0x31) }, |
4950 | { USB_DEVICE_WACOM(0x32) }, |
4951 | { USB_DEVICE_WACOM(0x33) }, |
4952 | { USB_DEVICE_WACOM(0x34) }, |
4953 | { USB_DEVICE_WACOM(0x35) }, |
4954 | { USB_DEVICE_WACOM(0x37) }, |
4955 | { USB_DEVICE_WACOM(0x38) }, |
4956 | { USB_DEVICE_WACOM(0x39) }, |
4957 | { USB_DEVICE_WACOM(0x3F) }, |
4958 | { USB_DEVICE_WACOM(0x41) }, |
4959 | { USB_DEVICE_WACOM(0x42) }, |
4960 | { USB_DEVICE_WACOM(0x43) }, |
4961 | { USB_DEVICE_WACOM(0x44) }, |
4962 | { USB_DEVICE_WACOM(0x45) }, |
4963 | { USB_DEVICE_WACOM(0x47) }, |
4964 | { USB_DEVICE_WACOM(0x57) }, |
4965 | { USB_DEVICE_WACOM(0x59) }, |
4966 | { USB_DEVICE_WACOM(0x5B) }, |
4967 | { USB_DEVICE_WACOM(0x5D) }, |
4968 | { USB_DEVICE_WACOM(0x5E) }, |
4969 | { USB_DEVICE_WACOM(0x60) }, |
4970 | { USB_DEVICE_WACOM(0x61) }, |
4971 | { USB_DEVICE_WACOM(0x62) }, |
4972 | { USB_DEVICE_WACOM(0x63) }, |
4973 | { USB_DEVICE_WACOM(0x64) }, |
4974 | { USB_DEVICE_WACOM(0x65) }, |
4975 | { USB_DEVICE_WACOM(0x69) }, |
4976 | { USB_DEVICE_WACOM(0x6A) }, |
4977 | { USB_DEVICE_WACOM(0x6B) }, |
4978 | { BT_DEVICE_WACOM(0x81) }, |
4979 | { USB_DEVICE_WACOM(0x84) }, |
4980 | { USB_DEVICE_WACOM(0x90) }, |
4981 | { USB_DEVICE_WACOM(0x93) }, |
4982 | { USB_DEVICE_WACOM(0x94) }, |
4983 | { USB_DEVICE_WACOM(0x97) }, |
4984 | { USB_DEVICE_WACOM(0x9A) }, |
4985 | { USB_DEVICE_WACOM(0x9F) }, |
4986 | { USB_DEVICE_WACOM(0xB0) }, |
4987 | { USB_DEVICE_WACOM(0xB1) }, |
4988 | { USB_DEVICE_WACOM(0xB2) }, |
4989 | { USB_DEVICE_WACOM(0xB3) }, |
4990 | { USB_DEVICE_WACOM(0xB4) }, |
4991 | { USB_DEVICE_WACOM(0xB5) }, |
4992 | { USB_DEVICE_WACOM(0xB7) }, |
4993 | { USB_DEVICE_WACOM(0xB8) }, |
4994 | { USB_DEVICE_WACOM(0xB9) }, |
4995 | { USB_DEVICE_WACOM(0xBA) }, |
4996 | { USB_DEVICE_WACOM(0xBB) }, |
4997 | { USB_DEVICE_WACOM(0xBC) }, |
4998 | { BT_DEVICE_WACOM(0xBD) }, |
4999 | { USB_DEVICE_WACOM(0xC0) }, |
5000 | { USB_DEVICE_WACOM(0xC2) }, |
5001 | { USB_DEVICE_WACOM(0xC4) }, |
5002 | { USB_DEVICE_WACOM(0xC5) }, |
5003 | { USB_DEVICE_WACOM(0xC6) }, |
5004 | { USB_DEVICE_WACOM(0xC7) }, |
5005 | { USB_DEVICE_WACOM(0xCC) }, |
5006 | { USB_DEVICE_WACOM(0xCE) }, |
5007 | { USB_DEVICE_WACOM(0xD0) }, |
5008 | { USB_DEVICE_WACOM(0xD1) }, |
5009 | { USB_DEVICE_WACOM(0xD2) }, |
5010 | { USB_DEVICE_WACOM(0xD3) }, |
5011 | { USB_DEVICE_WACOM(0xD4) }, |
5012 | { USB_DEVICE_WACOM(0xD5) }, |
5013 | { USB_DEVICE_WACOM(0xD6) }, |
5014 | { USB_DEVICE_WACOM(0xD7) }, |
5015 | { USB_DEVICE_WACOM(0xD8) }, |
5016 | { USB_DEVICE_WACOM(0xDA) }, |
5017 | { USB_DEVICE_WACOM(0xDB) }, |
5018 | { USB_DEVICE_WACOM(0xDD) }, |
5019 | { USB_DEVICE_WACOM(0xDE) }, |
5020 | { USB_DEVICE_WACOM(0xDF) }, |
5021 | { USB_DEVICE_WACOM(0xE2) }, |
5022 | { USB_DEVICE_WACOM(0xE3) }, |
5023 | { USB_DEVICE_WACOM(0xE5) }, |
5024 | { USB_DEVICE_WACOM(0xE6) }, |
5025 | { USB_DEVICE_WACOM(0xEC) }, |
5026 | { USB_DEVICE_WACOM(0xED) }, |
5027 | { USB_DEVICE_WACOM(0xEF) }, |
5028 | { USB_DEVICE_WACOM(0xF0) }, |
5029 | { USB_DEVICE_WACOM(0xF4) }, |
5030 | { USB_DEVICE_WACOM(0xF6) }, |
5031 | { USB_DEVICE_WACOM(0xF8) }, |
5032 | { USB_DEVICE_WACOM(0xFA) }, |
5033 | { USB_DEVICE_WACOM(0xFB) }, |
5034 | { USB_DEVICE_WACOM(0x100) }, |
5035 | { USB_DEVICE_WACOM(0x101) }, |
5036 | { USB_DEVICE_WACOM(0x10D) }, |
5037 | { USB_DEVICE_WACOM(0x10E) }, |
5038 | { USB_DEVICE_WACOM(0x10F) }, |
5039 | { USB_DEVICE_WACOM(0x116) }, |
5040 | { USB_DEVICE_WACOM(0x12C) }, |
5041 | { USB_DEVICE_WACOM(0x300) }, |
5042 | { USB_DEVICE_WACOM(0x301) }, |
5043 | { USB_DEVICE_WACOM(0x302) }, |
5044 | { USB_DEVICE_WACOM(0x303) }, |
5045 | { USB_DEVICE_WACOM(0x304) }, |
5046 | { USB_DEVICE_WACOM(0x307) }, |
5047 | { USB_DEVICE_WACOM(0x309) }, |
5048 | { USB_DEVICE_WACOM(0x30A) }, |
5049 | { USB_DEVICE_WACOM(0x30C) }, |
5050 | { USB_DEVICE_WACOM(0x30E) }, |
5051 | { USB_DEVICE_WACOM(0x314) }, |
5052 | { USB_DEVICE_WACOM(0x315) }, |
5053 | { USB_DEVICE_WACOM(0x317) }, |
5054 | { USB_DEVICE_WACOM(0x318) }, |
5055 | { USB_DEVICE_WACOM(0x319) }, |
5056 | { USB_DEVICE_WACOM(0x323) }, |
5057 | { USB_DEVICE_WACOM(0x325) }, |
5058 | { USB_DEVICE_WACOM(0x326) }, |
5059 | { USB_DEVICE_WACOM(0x32A) }, |
5060 | { USB_DEVICE_WACOM(0x32B) }, |
5061 | { USB_DEVICE_WACOM(0x32C) }, |
5062 | { USB_DEVICE_WACOM(0x32F) }, |
5063 | { USB_DEVICE_WACOM(0x331) }, |
5064 | { USB_DEVICE_WACOM(0x333) }, |
5065 | { USB_DEVICE_WACOM(0x335) }, |
5066 | { USB_DEVICE_WACOM(0x336) }, |
5067 | { USB_DEVICE_WACOM(0x33B) }, |
5068 | { USB_DEVICE_WACOM(0x33C) }, |
5069 | { USB_DEVICE_WACOM(0x33D) }, |
5070 | { USB_DEVICE_WACOM(0x33E) }, |
5071 | { USB_DEVICE_WACOM(0x343) }, |
5072 | { BT_DEVICE_WACOM(0x360) }, |
5073 | { BT_DEVICE_WACOM(0x361) }, |
5074 | { BT_DEVICE_WACOM(0x377) }, |
5075 | { BT_DEVICE_WACOM(0x379) }, |
5076 | { USB_DEVICE_WACOM(0x37A) }, |
5077 | { USB_DEVICE_WACOM(0x37B) }, |
5078 | { BT_DEVICE_WACOM(0x393) }, |
5079 | { BT_DEVICE_WACOM(0x3c6) }, |
5080 | { BT_DEVICE_WACOM(0x3c8) }, |
5081 | { BT_DEVICE_WACOM(0x3dd) }, |
5082 | { USB_DEVICE_WACOM(0x4001) }, |
5083 | { USB_DEVICE_WACOM(0x4004) }, |
5084 | { USB_DEVICE_WACOM(0x5000) }, |
5085 | { USB_DEVICE_WACOM(0x5002) }, |
5086 | { USB_DEVICE_LENOVO(0x6004) }, |
5087 | |
5088 | { USB_DEVICE_WACOM(HID_ANY_ID) }, |
5089 | { I2C_DEVICE_WACOM(HID_ANY_ID) }, |
5090 | { BT_DEVICE_WACOM(HID_ANY_ID) }, |
5091 | { } |
5092 | }; |
5093 | MODULE_DEVICE_TABLE(hid, wacom_ids); |
5094 | |