wacom_wac.c 150 KB
Newer Older
1
/*
2
 * drivers/input/tablet/wacom_wac.c
3
 *
4
 *  USB Wacom tablet support - Wacom specific code
5
6
7
8
9
10
11
12
13
 *
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
14

15
#include "wacom_wac.h"
16
#include "wacom.h"
17
#include <linux/input/mt.h>
18

19
20
21
22
23
24
25
26
/* resolution for penabled devices */
#define WACOM_PL_RES		20
#define WACOM_PENPRTN_RES	40
#define WACOM_VOLITO_RES	50
#define WACOM_GRAPHIRE_RES	80
#define WACOM_INTUOS_RES	100
#define WACOM_INTUOS3_RES	200

27
28
29
30
/* Newer Cintiq and DTU have an offset between tablet and screen areas */
#define WACOM_DTU_OFFSET	200
#define WACOM_CINTIQ_OFFSET	400

31
32
/*
 * Scale factor relating reported contact size to logical contact area.
33
34
35
36
 * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo
 */
#define WACOM_CONTACT_AREA_SCALE 2607

37
38
39
40
static bool touch_arbitration = 1;
module_param(touch_arbitration, bool, 0644);
MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");

41
42
43
static void wacom_report_numbered_buttons(struct input_dev *input_dev,
				int button_count, int mask);

44
45
static int wacom_numbered_button_to_key(int n);

46
47
static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
			     int group);
48
49
50
51
52
53
/*
 * Percent of battery capacity for Graphire.
 * 8th value means AC online and show 100% capacity.
 */
static unsigned short batcap_gr[8] = { 1, 15, 25, 35, 50, 70, 100, 100 };

54
55
56
57
58
/*
 * Percent of battery capacity for Intuos4 WL, AC has a separate bit.
 */
static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 };

59
static void __wacom_notify_battery(struct wacom_battery *battery,
60
61
62
				   int bat_status, int bat_capacity,
				   bool bat_charging, bool bat_connected,
				   bool ps_connected)
63
{
64
65
	bool changed = battery->bat_status       != bat_status    ||
		       battery->battery_capacity != bat_capacity  ||
66
67
68
69
70
		       battery->bat_charging     != bat_charging  ||
		       battery->bat_connected    != bat_connected ||
		       battery->ps_connected     != ps_connected;

	if (changed) {
71
		battery->bat_status = bat_status;
72
73
74
75
76
77
78
79
80
81
		battery->battery_capacity = bat_capacity;
		battery->bat_charging = bat_charging;
		battery->bat_connected = bat_connected;
		battery->ps_connected = ps_connected;

		if (battery->battery)
			power_supply_changed(battery->battery);
	}
}

82
static void wacom_notify_battery(struct wacom_wac *wacom_wac,
83
84
	int bat_status, int bat_capacity, bool bat_charging,
	bool bat_connected, bool ps_connected)
85
86
87
{
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);

88
89
	__wacom_notify_battery(&wacom->battery, bat_status, bat_capacity,
			       bat_charging, bat_connected, ps_connected);
90
91
}

92
static int wacom_penpartner_irq(struct wacom_wac *wacom)
93
94
{
	unsigned char *data = wacom->data;
95
	struct input_dev *input = wacom->pen_input;
96
97

	switch (data[0]) {
98
99
100
101
	case 1:
		if (data[5] & 0x80) {
			wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
			wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
102
103
			input_report_key(input, wacom->tool[0], 1);
			input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
104
105
			input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
			input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
106
107
108
			input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
			input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127));
			input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
109
		} else {
110
111
112
113
			input_report_key(input, wacom->tool[0], 0);
			input_report_abs(input, ABS_MISC, 0); /* report tool id */
			input_report_abs(input, ABS_PRESSURE, -1);
			input_report_key(input, BTN_TOUCH, 0);
114
115
		}
		break;
116

117
	case 2:
118
119
		input_report_key(input, BTN_TOOL_PEN, 1);
		input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
120
121
		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
122
123
124
		input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127);
		input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
		input_report_key(input, BTN_STYLUS, (data[5] & 0x40));
125
		break;
126

127
	default:
128
129
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
130
		return 0;
131
        }
132

133
134
135
	return 1;
}

136
static int wacom_pl_irq(struct wacom_wac *wacom)
137
{
138
	struct wacom_features *features = &wacom->features;
139
	unsigned char *data = wacom->data;
140
	struct input_dev *input = wacom->pen_input;
141
	int prox, pressure;
142

143
	if (data[0] != WACOM_REPORT_PENABLED) {
144
145
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
146
147
148
149
150
		return 0;
	}

	prox = data[1] & 0x40;

151
152
153
154
	if (!wacom->id[0]) {
		if ((data[0] & 0x10) || (data[4] & 0x20)) {
			wacom->tool[0] = BTN_TOOL_RUBBER;
			wacom->id[0] = ERASER_DEVICE_ID;
155
		}
156
157
		else {
			wacom->tool[0] = BTN_TOOL_PEN;
158
			wacom->id[0] = STYLUS_DEVICE_ID;
159
160
		}
	}
161

162
163
164
165
166
167
168
169
170
171
	/* If the eraser is in prox, STYLUS2 is always set. If we
	 * mis-detected the type and notice that STYLUS2 isn't set
	 * then force the eraser out of prox and let the pen in.
	 */
	if (wacom->tool[0] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
		input_report_key(input, BTN_TOOL_RUBBER, 0);
		input_report_abs(input, ABS_MISC, 0);
		input_sync(input);
		wacom->tool[0] = BTN_TOOL_PEN;
		wacom->id[0] = STYLUS_DEVICE_ID;
172
173
	}

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
	if (prox) {
		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
		if (features->pressure_max > 255)
			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
		pressure += (features->pressure_max + 1) / 2;

		input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
		input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
		input_report_abs(input, ABS_PRESSURE, pressure);

		input_report_key(input, BTN_TOUCH, data[4] & 0x08);
		input_report_key(input, BTN_STYLUS, data[4] & 0x10);
		/* Only allow the stylus2 button to be reported for the pen tool. */
		input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
	}
189
190
191
192
193

	if (!prox)
		wacom->id[0] = 0;
	input_report_key(input, wacom->tool[0], prox);
	input_report_abs(input, ABS_MISC, wacom->id[0]);
194
195
196
	return 1;
}

197
static int wacom_ptu_irq(struct wacom_wac *wacom)
198
199
{
	unsigned char *data = wacom->data;
200
	struct input_dev *input = wacom->pen_input;
201

202
	if (data[0] != WACOM_REPORT_PENABLED) {
203
204
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
205
206
207
208
		return 0;
	}

	if (data[1] & 0x04) {
209
210
		input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20);
		input_report_key(input, BTN_TOUCH, data[1] & 0x08);
211
		wacom->id[0] = ERASER_DEVICE_ID;
212
	} else {
213
214
		input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20);
		input_report_key(input, BTN_TOUCH, data[1] & 0x01);
215
		wacom->id[0] = STYLUS_DEVICE_ID;
216
	}
217
	input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
218
219
220
	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
	input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
221
222
	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
223
224
225
	return 1;
}

226
227
static int wacom_dtu_irq(struct wacom_wac *wacom)
{
228
	unsigned char *data = wacom->data;
229
	struct input_dev *input = wacom->pen_input;
230
	int prox = data[1] & 0x20;
231

232
233
	dev_dbg(input->dev.parent,
		"%s: received report #%d", __func__, data[0]);
234
235
236
237
238
239
240
241
242
243
244
245
246

	if (prox) {
		/* Going into proximity select tool */
		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
		if (wacom->tool[0] == BTN_TOOL_PEN)
			wacom->id[0] = STYLUS_DEVICE_ID;
		else
			wacom->id[0] = ERASER_DEVICE_ID;
	}
	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
	input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
	input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
247
	input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
248
249
250
251
252
253
254
255
	input_report_key(input, BTN_TOUCH, data[1] & 0x05);
	if (!prox) /* out-prox */
		wacom->id[0] = 0;
	input_report_key(input, wacom->tool[0], prox);
	input_report_abs(input, ABS_MISC, wacom->id[0]);
	return 1;
}

256
257
static int wacom_dtus_irq(struct wacom_wac *wacom)
{
258
	unsigned char *data = wacom->data;
259
	struct input_dev *input = wacom->pen_input;
260
261
262
263
264
265
266
	unsigned short prox, pressure = 0;

	if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) {
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d", __func__, data[0]);
		return 0;
	} else if (data[0] == WACOM_REPORT_DTUSPAD) {
267
		input = wacom->pad_input;
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
		input_report_key(input, BTN_0, (data[1] & 0x01));
		input_report_key(input, BTN_1, (data[1] & 0x02));
		input_report_key(input, BTN_2, (data[1] & 0x04));
		input_report_key(input, BTN_3, (data[1] & 0x08));
		input_report_abs(input, ABS_MISC,
				 data[1] & 0x0f ? PAD_DEVICE_ID : 0);
		return 1;
	} else {
		prox = data[1] & 0x80;
		if (prox) {
			switch ((data[1] >> 3) & 3) {
			case 1: /* Rubber */
				wacom->tool[0] = BTN_TOOL_RUBBER;
				wacom->id[0] = ERASER_DEVICE_ID;
				break;

			case 2: /* Pen */
				wacom->tool[0] = BTN_TOOL_PEN;
				wacom->id[0] = STYLUS_DEVICE_ID;
				break;
			}
		}

		input_report_key(input, BTN_STYLUS, data[1] & 0x20);
		input_report_key(input, BTN_STYLUS2, data[1] & 0x40);
		input_report_abs(input, ABS_X, get_unaligned_be16(&data[3]));
		input_report_abs(input, ABS_Y, get_unaligned_be16(&data[5]));
		pressure = ((data[1] & 0x03) << 8) | (data[2] & 0xff);
		input_report_abs(input, ABS_PRESSURE, pressure);
		input_report_key(input, BTN_TOUCH, pressure > 10);

		if (!prox) /* out-prox */
			wacom->id[0] = 0;
		input_report_key(input, wacom->tool[0], prox);
		input_report_abs(input, ABS_MISC, wacom->id[0]);
		return 1;
	}
}

307
static int wacom_graphire_irq(struct wacom_wac *wacom)
308
{
309
	struct wacom_features *features = &wacom->features;
310
	unsigned char *data = wacom->data;
311
	struct input_dev *input = wacom->pen_input;
312
	struct input_dev *pad_input = wacom->pad_input;
313
	int battery_capacity, ps_connected;
314
	int prox;
315
316
	int rw = 0;
	int retval = 0;
317

318
319
320
321
322
323
324
325
	if (features->type == GRAPHIRE_BT) {
		if (data[0] != WACOM_REPORT_PENABLED_BT) {
			dev_dbg(input->dev.parent,
				"%s: received unknown report #%d\n", __func__,
				data[0]);
			goto exit;
		}
	} else if (data[0] != WACOM_REPORT_PENABLED) {
326
327
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
328
		goto exit;
329
330
	}

331
332
333
334
	prox = data[1] & 0x80;
	if (prox || wacom->id[0]) {
		if (prox) {
			switch ((data[1] >> 5) & 3) {
335
336
337

			case 0:	/* Pen */
				wacom->tool[0] = BTN_TOOL_PEN;
338
				wacom->id[0] = STYLUS_DEVICE_ID;
339
340
341
342
				break;

			case 1: /* Rubber */
				wacom->tool[0] = BTN_TOOL_RUBBER;
343
				wacom->id[0] = ERASER_DEVICE_ID;
344
345
346
				break;

			case 2: /* Mouse with wheel */
347
				input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
348
349
350
351
				/* fall through */

			case 3: /* Mouse without wheel */
				wacom->tool[0] = BTN_TOOL_MOUSE;
352
				wacom->id[0] = CURSOR_DEVICE_ID;
353
				break;
354
			}
355
		}
356
357
		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
358
		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
359
360
361
362
363
364
			if (features->type == GRAPHIRE_BT)
				input_report_abs(input, ABS_PRESSURE, data[6] |
					(((__u16) (data[1] & 0x08)) << 5));
			else
				input_report_abs(input, ABS_PRESSURE, data[6] |
					((data[7] & 0x03) << 8));
365
366
367
			input_report_key(input, BTN_TOUCH, data[1] & 0x01);
			input_report_key(input, BTN_STYLUS, data[1] & 0x02);
			input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
368
		} else {
369
370
			input_report_key(input, BTN_LEFT, data[1] & 0x01);
			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
371
372
			if (features->type == WACOM_G4 ||
					features->type == WACOM_MO) {
373
				input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
374
				rw = (data[7] & 0x04) - (data[7] & 0x03);
375
376
377
378
379
380
381
382
383
384
385
386
387
388
			} else if (features->type == GRAPHIRE_BT) {
				/* Compute distance between mouse and tablet */
				rw = 44 - (data[6] >> 2);
				rw = clamp_val(rw, 0, 31);
				input_report_abs(input, ABS_DISTANCE, rw);
				if (((data[1] >> 5) & 3) == 2) {
					/* Mouse with wheel */
					input_report_key(input, BTN_MIDDLE,
							data[1] & 0x04);
					rw = (data[6] & 0x01) ? -1 :
						(data[6] & 0x02) ? 1 : 0;
				} else {
					rw = 0;
				}
389
			} else {
390
				input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
391
				rw = -(signed char)data[6];
392
			}
393
			input_report_rel(input, REL_WHEEL, rw);
394
		}
395
396
397

		if (!prox)
			wacom->id[0] = 0;
398
399
400
		input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
		input_report_key(input, wacom->tool[0], prox);
		input_sync(input); /* sync last event */
Ping Cheng's avatar
Ping Cheng committed
401
	}
402
403

	/* send pad data */
404
	switch (features->type) {
405
	case WACOM_G4:
406
407
		prox = data[7] & 0xf8;
		if (prox || wacom->id[1]) {
408
			wacom->id[1] = PAD_DEVICE_ID;
409
410
			input_report_key(pad_input, BTN_BACK, (data[7] & 0x40));
			input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x80));
411
			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
412
			input_report_rel(pad_input, REL_WHEEL, rw);
413
414
			if (!prox)
				wacom->id[1] = 0;
415
			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
416
			retval = 1;
417
		}
418
		break;
419
420

	case WACOM_MO:
421
422
		prox = (data[7] & 0xf8) || data[8];
		if (prox || wacom->id[1]) {
423
			wacom->id[1] = PAD_DEVICE_ID;
424
425
426
427
428
			input_report_key(pad_input, BTN_BACK, (data[7] & 0x08));
			input_report_key(pad_input, BTN_LEFT, (data[7] & 0x20));
			input_report_key(pad_input, BTN_FORWARD, (data[7] & 0x10));
			input_report_key(pad_input, BTN_RIGHT, (data[7] & 0x40));
			input_report_abs(pad_input, ABS_WHEEL, (data[8] & 0x7f));
429
430
			if (!prox)
				wacom->id[1] = 0;
431
			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
432
			retval = 1;
433
434
		}
		break;
435
436
437
438
439
440
	case GRAPHIRE_BT:
		prox = data[7] & 0x03;
		if (prox || wacom->id[1]) {
			wacom->id[1] = PAD_DEVICE_ID;
			input_report_key(pad_input, BTN_0, (data[7] & 0x02));
			input_report_key(pad_input, BTN_1, (data[7] & 0x01));
441
442
			if (!prox)
				wacom->id[1] = 0;
443
			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
444
			retval = 1;
445
446
		}
		break;
447
	}
448
449
450
451
452
453

	/* Store current battery capacity and power supply state */
	if (features->type == GRAPHIRE_BT) {
		rw = (data[7] >> 2 & 0x07);
		battery_capacity = batcap_gr[rw];
		ps_connected = rw == 7;
454
455
456
		wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
				     battery_capacity, ps_connected, 1,
				     ps_connected);
457
	}
458
459
exit:
	return retval;
460
461
}

462
463
464
static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
{
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
465
	struct wacom_features *features = &wacom_wac->features;
466
467
468
469
	struct hid_report *r;
	struct hid_report_enum *re;

	re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
470
471
472
473
	if (features->type == INTUOSHT2)
		r = re->report_id_hash[WACOM_REPORT_INTUOSHT2_ID];
	else
		r = re->report_id_hash[WACOM_REPORT_INTUOS_ID1];
474
475
476
477
478
	if (r) {
		hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
	}
}

479
480
481
482
483
static int wacom_intuos_pad(struct wacom_wac *wacom)
{
	struct wacom_features *features = &wacom->features;
	unsigned char *data = wacom->data;
	struct input_dev *input = wacom->pad_input;
484
485
486
487
488
489
	int i;
	int buttons = 0, nbuttons = features->numbered_buttons;
	int keys = 0, nkeys = 0;
	int ring1 = 0, ring2 = 0;
	int strip1 = 0, strip2 = 0;
	bool prox = false;
490
491
492
493
494
495
496

	/* pad packets. Works as a second tool and is always in prox */
	if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
	      data[0] == WACOM_REPORT_CINTIQPAD))
		return 0;

	if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
497
498
		buttons = (data[3] << 1) | (data[2] & 0x01);
		ring1 = data[1];
499
	} else if (features->type == DTK) {
500
		buttons = data[6];
501
	} else if (features->type == WACOM_13HD) {
502
		buttons = (data[4] << 1) | (data[3] & 0x01);
503
	} else if (features->type == WACOM_24HD) {
504
505
506
		buttons = (data[8] << 8) | data[6];
		ring1 = data[1];
		ring2 = data[2];
507
508
509
510
511
512
513
514

		/*
		 * Three "buttons" are available on the 24HD which are
		 * physically implemented as a touchstrip. Each button
		 * is approximately 3 bits wide with a 2 bit spacing.
		 * The raw touchstrip bits are stored at:
		 *    ((data[3] & 0x1f) << 8) | data[4])
		 */
515
516
517
518
		nkeys = 3;
		keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
		       ((data[4] & 0xE0) ? 1<<1 : 0) |
		       ((data[4] & 0x07) ? 1<<0 : 0);
519
	} else if (features->type == WACOM_27QHD) {
520
521
		nkeys = 3;
		keys = data[2] & 0x07;
522
523
524
525
526
527
528
529
530

		input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
		input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
		input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
	} else if (features->type == CINTIQ_HYBRID) {
		/*
		 * Do not send hardware buttons under Android. They
		 * are already sent to the system through GPIO (and
		 * have different meaning).
531
532
533
534
535
536
		 *
		 * d-pad right  -> data[4] & 0x10
		 * d-pad up     -> data[4] & 0x20
		 * d-pad left   -> data[4] & 0x40
		 * d-pad down   -> data[4] & 0x80
		 * d-pad center -> data[3] & 0x01
537
		 */
538
		buttons = (data[4] << 1) | (data[3] & 0x01);
539
	} else if (features->type == CINTIQ_COMPANION_2) {
540
541
542
543
544
		/* d-pad right  -> data[2] & 0x10
		 * d-pad up     -> data[2] & 0x20
		 * d-pad left   -> data[2] & 0x40
		 * d-pad down   -> data[2] & 0x80
		 * d-pad center -> data[1] & 0x01
545
		 */
546
		buttons = ((data[2] >> 4) << 7) |
547
		          ((data[1] & 0x04) << 4) |
548
549
		          ((data[2] & 0x0F) << 2) |
		          (data[1] & 0x03);
550
551
552
553
554
	} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
		/*
		 * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
		 * addition to the mechanical switch. Switch data is
		 * stored in data[4], capacitive data in data[5].
555
556
		 *
		 * Touch ring mode switch (data[3]) has no capacitive sensor
557
		 */
558
559
		buttons = (data[4] << 1) | (data[3] & 0x01);
		ring1 = data[2];
560
561
	} else {
		if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
562
563
			buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
			          (data[6] << 1) | (data[5] & 0x01);
564
565

			if (features->type == WACOM_22HD) {
566
567
				nkeys = 3;
				keys = data[9] & 0x07;
568
569
			}
		} else {
570
571
			buttons = ((data[6] & 0x10) << 5)  |
			          ((data[5] & 0x10) << 4)  |
572
573
			          ((data[6] & 0x0F) << 4)  |
			          (data[5] & 0x0F);
574
		}
575
576
		strip1 = ((data[1] & 0x1f) << 8) | data[2];
		strip2 = ((data[3] & 0x1f) << 8) | data[4];
577
	}
578

579
	prox = (buttons & ~(~0U << nbuttons)) | (keys & ~(~0U << nkeys)) |
580
	       (ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2;
581
582
583
584
585
586
587

	wacom_report_numbered_buttons(input, nbuttons, buttons);

	for (i = 0; i < nkeys; i++)
		input_report_key(input, KEY_PROG1 + i, keys & (1 << i));

	input_report_abs(input, ABS_RX, strip1);
588
	input_report_abs(input, ABS_RY, strip2);
589

590
591
	input_report_abs(input, ABS_WHEEL,    (ring1 & 0x80) ? (ring1 & 0x7f) : 0);
	input_report_abs(input, ABS_THROTTLE, (ring2 & 0x80) ? (ring2 & 0x7f) : 0);
592
593
594
595
596
597

	input_report_key(input, wacom->tool[1], prox ? 1 : 0);
	input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);

	input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);

598
599
600
	return 1;
}

601
602
603
604
605
static int wacom_intuos_id_mangle(int tool_id)
{
	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
}

606
607
608
609
610
611
612
static int wacom_intuos_get_tool_type(int tool_id)
{
	int tool_type;

	switch (tool_id) {
	case 0x812: /* Inking pen */
	case 0x801: /* Intuos3 Inking pen */
613
	case 0x12802: /* Intuos4/5 Inking Pen */
614
615
616
617
618
619
620
621
622
623
624
625
626
627
	case 0x012:
		tool_type = BTN_TOOL_PENCIL;
		break;

	case 0x822: /* Pen */
	case 0x842:
	case 0x852:
	case 0x823: /* Intuos3 Grip Pen */
	case 0x813: /* Intuos3 Classic Pen */
	case 0x885: /* Intuos3 Marker Pen */
	case 0x802: /* Intuos4/5 13HD/24HD General Pen */
	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
	case 0x8e2: /* IntuosHT2 pen */
	case 0x022:
628
629
630
631
632
	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
	case 0x16802: /* Cintiq 13HD Pro Pen */
	case 0x18802: /* DTH2242 Pen */
	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
		tool_type = BTN_TOOL_PEN;
		break;

	case 0x832: /* Stroke pen */
	case 0x032:
		tool_type = BTN_TOOL_BRUSH;
		break;

	case 0x007: /* Mouse 4D and 2D */
	case 0x09c:
	case 0x094:
	case 0x017: /* Intuos3 2D Mouse */
	case 0x806: /* Intuos4 Mouse */
		tool_type = BTN_TOOL_MOUSE;
		break;

	case 0x096: /* Lens cursor */
	case 0x097: /* Intuos3 Lens cursor */
	case 0x006: /* Intuos4 Lens cursor */
		tool_type = BTN_TOOL_LENS;
		break;

	case 0x82a: /* Eraser */
656
	case 0x84a:
657
658
659
660
661
662
663
664
665
666
	case 0x85a:
	case 0x91a:
	case 0xd1a:
	case 0x0fa:
	case 0x82b: /* Intuos3 Grip Pen Eraser */
	case 0x81b: /* Intuos3 Classic Pen Eraser */
	case 0x91b: /* Intuos3 Airbrush Eraser */
	case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
	case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
	case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
667
668
669
670
671
672
	case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
	case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
	case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
	case 0x1880a: /* DTH2242 Eraser */
	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
673
674
675
676
677
678
679
680
		tool_type = BTN_TOOL_RUBBER;
		break;

	case 0xd12:
	case 0x912:
	case 0x112:
	case 0x913: /* Intuos3 Airbrush */
	case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
681
	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
682
683
684
685
686
687
688
689
690
691
		tool_type = BTN_TOOL_AIRBRUSH;
		break;

	default: /* Unknown tool */
		tool_type = BTN_TOOL_PEN;
		break;
	}
	return tool_type;
}

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
static void wacom_exit_report(struct wacom_wac *wacom)
{
	struct input_dev *input = wacom->pen_input;
	struct wacom_features *features = &wacom->features;
	unsigned char *data = wacom->data;
	int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;

	/*
	 * Reset all states otherwise we lose the initial states
	 * when in-prox next time
	 */
	input_report_abs(input, ABS_X, 0);
	input_report_abs(input, ABS_Y, 0);
	input_report_abs(input, ABS_DISTANCE, 0);
	input_report_abs(input, ABS_TILT_X, 0);
	input_report_abs(input, ABS_TILT_Y, 0);
	if (wacom->tool[idx] >= BTN_TOOL_MOUSE) {
		input_report_key(input, BTN_LEFT, 0);
		input_report_key(input, BTN_MIDDLE, 0);
		input_report_key(input, BTN_RIGHT, 0);
		input_report_key(input, BTN_SIDE, 0);
		input_report_key(input, BTN_EXTRA, 0);
		input_report_abs(input, ABS_THROTTLE, 0);
		input_report_abs(input, ABS_RZ, 0);
	} else {
		input_report_abs(input, ABS_PRESSURE, 0);
		input_report_key(input, BTN_STYLUS, 0);
		input_report_key(input, BTN_STYLUS2, 0);
		input_report_key(input, BTN_TOUCH, 0);
		input_report_abs(input, ABS_WHEEL, 0);
		if (features->type >= INTUOS3S)
			input_report_abs(input, ABS_Z, 0);
	}
	input_report_key(input, wacom->tool[idx], 0);
	input_report_abs(input, ABS_MISC, 0); /* reset tool id */
	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
	wacom->id[idx] = 0;
}

731
static int wacom_intuos_inout(struct wacom_wac *wacom)
732
{
733
	struct wacom_features *features = &wacom->features;
734
	unsigned char *data = wacom->data;
735
	struct input_dev *input = wacom->pen_input;
736
	int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
737

738
739
740
741
	if (!(((data[1] & 0xfc) == 0xc0) ||  /* in prox */
	    ((data[1] & 0xfe) == 0x20) ||    /* in range */
	    ((data[1] & 0xfe) == 0x80)))     /* out prox */
		return 0;
742
743
744
745
746
747
748
749

	/* Enter report */
	if ((data[1] & 0xfc) == 0xc0) {
		/* serial number of the tool */
		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
			(data[4] << 20) + (data[5] << 12) +
			(data[6] << 4) + (data[7] >> 4);

750
		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
751
		     ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8);
752

753
754
		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);

755
		wacom->shared->stylus_in_proximity = true;
756
757
758
		return 1;
	}

759
760
	/* in Range */
	if ((data[1] & 0xfe) == 0x20) {
761
762
		if (features->type != INTUOSHT2)
			wacom->shared->stylus_in_proximity = true;
763

764
765
766
767
768
769
770
771
		/* in Range while exiting */
		if (wacom->reporting_data) {
			input_report_key(input, BTN_TOUCH, 0);
			input_report_abs(input, ABS_PRESSURE, 0);
			input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
			return 2;
		}
		return 1;
772
773
	}

774
775
	/* Exit report */
	if ((data[1] & 0xfe) == 0x80) {
776
		wacom->shared->stylus_in_proximity = false;
777
		wacom->reporting_data = false;
778

779
780
781
782
		/* don't report exit if we don't know the ID */
		if (!wacom->id[idx])
			return 1;

783
		wacom_exit_report(wacom);
Ping Cheng's avatar
Ping Cheng committed
784
		return 2;
785
	}
786

787
788
789
	return 0;
}

790
791
792
793
static inline bool report_touch_events(struct wacom_wac *wacom)
{
	return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1);
}
794

795
796
797
static inline bool delay_pen_events(struct wacom_wac *wacom)
{
	return (wacom->shared->touch_down && touch_arbitration);
798
799
}

800
static int wacom_intuos_general(struct wacom_wac *wacom)
801
{
802
	struct wacom_features *features = &wacom->features;
803
	unsigned char *data = wacom->data;
804
	struct input_dev *input = wacom->pen_input;
805
	int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
806
	unsigned char type = (data[1] >> 1) & 0x0F;
807
	unsigned int x, y, distance, t;
808

809
810
811
812
	if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_CINTIQ &&
		data[0] != WACOM_REPORT_INTUOS_PEN)
		return 0;

813
	if (delay_pen_events(wacom))
814
815
		return 1;

816
817
818
819
820
821
822
	/* don't report events if we don't know the tool ID */
	if (!wacom->id[idx]) {
		/* but reschedule a read of the current tool */
		wacom_intuos_schedule_prox_event(wacom);
		return 1;
	}

823
824
825
826
	/*
	 * don't report events for invalid data
	 */
	/* older I4 styli don't work with new Cintiqs */
827
	if ((!((wacom->id[idx] >> 16) & 0x01) &&
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
			(features->type == WACOM_21UX2)) ||
	    /* Only large Intuos support Lense Cursor */
	    (wacom->tool[idx] == BTN_TOOL_LENS &&
		(features->type == INTUOS3 ||
		 features->type == INTUOS3S ||
		 features->type == INTUOS4 ||
		 features->type == INTUOS4S ||
		 features->type == INTUOS5 ||
		 features->type == INTUOS5S ||
		 features->type == INTUOSPM ||
		 features->type == INTUOSPS)) ||
	   /* Cintiq doesn't send data when RDY bit isn't set */
	   (features->type == CINTIQ && !(data[1] & 0x40)))
		return 1;

843
844
845
846
847
848
849
	x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
	y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
	distance = data[9] >> 2;
	if (features->type < INTUOS3S) {
		x >>= 1;
		y >>= 1;
		distance >>= 1;
850
	}
851
852
	if (features->type == INTUOSHT2)
		distance = features->distance_max - distance;
853
854
855
	input_report_abs(input, ABS_X, x);
	input_report_abs(input, ABS_Y, y);
	input_report_abs(input, ABS_DISTANCE, distance);
856

857
858
859
860
861
862
	switch (type) {
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
		/* general pen packet */
863
864
865
		t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1);
		if (features->pressure_max < 2047)
			t >>= 1;
866
		input_report_abs(input, ABS_PRESSURE, t);
867
868
		if (features->type != INTUOSHT2) {
		    input_report_abs(input, ABS_TILT_X,
869
				 (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
870
871
		    input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
		}
872
873
874
		input_report_key(input, BTN_STYLUS, data[1] & 2);
		input_report_key(input, BTN_STYLUS2, data[1] & 4);
		input_report_key(input, BTN_TOUCH, t > 10);
875
		break;
876

877
878
	case 0x0a:
		/* airbrush second packet */
879
		input_report_abs(input, ABS_WHEEL,
880
				(data[6] << 2) | ((data[7] >> 6) & 3));
881
		input_report_abs(input, ABS_TILT_X,
882
883
				 (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
		input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
884
		break;
885

886
887
888
889
890
891
892
893
894
	case 0x05:
		/* Rotation packet */
		if (features->type >= INTUOS3S) {
			/* I3 marker pen rotation */
			t = (data[6] << 3) | ((data[7] >> 5) & 7);
			t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
				((t-1) / 2 + 450)) : (450 - t / 2) ;
			input_report_abs(input, ABS_Z, t);
		} else {
895
			/* 4D mouse 2nd packet */
896
897
898
899
900
			t = (data[6] << 3) | ((data[7] >> 5) & 7);
			input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
				((t - 1) / 2) : -t / 2);
		}
		break;
901

902
	case 0x04:
903
904
905
906
907
908
909
910
911
912
913
		/* 4D mouse 1st packet */
		input_report_key(input, BTN_LEFT,   data[8] & 0x01);
		input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
		input_report_key(input, BTN_RIGHT,  data[8] & 0x04);

		input_report_key(input, BTN_SIDE,   data[8] & 0x20);
		input_report_key(input, BTN_EXTRA,  data[8] & 0x10);
		t = (data[6] << 2) | ((data[7] >> 6) & 3);
		input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
		break;

914
	case 0x06:
915
916
917
918
919
920
921
922
		/* I4 mouse */
		input_report_key(input, BTN_LEFT,   data[6] & 0x01);
		input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
		input_report_key(input, BTN_RIGHT,  data[6] & 0x04);
		input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
				 - ((data[7] & 0x40) >> 6));
		input_report_key(input, BTN_SIDE,   data[6] & 0x08);
		input_report_key(input, BTN_EXTRA,  data[6] & 0x10);
923

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
		input_report_abs(input, ABS_TILT_X,
			(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
		input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
		break;

	case 0x08:
		if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
			/* 2D mouse packet */
			input_report_key(input, BTN_LEFT,   data[8] & 0x04);
			input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
			input_report_key(input, BTN_RIGHT,  data[8] & 0x10);
			input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
					 - ((data[8] & 0x02) >> 1));

			/* I3 2D mouse side buttons */
			if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
				input_report_key(input, BTN_SIDE,   data[8] & 0x40);
				input_report_key(input, BTN_EXTRA,  data[8] & 0x20);
942
			}
943
		}
944
		else if (wacom->tool[idx] == BTN_TOOL_LENS) {
945
			/* Lens cursor packets */
946
947
948
949
950
			input_report_key(input, BTN_LEFT,   data[8] & 0x01);
			input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
			input_report_key(input, BTN_RIGHT,  data[8] & 0x04);
			input_report_key(input, BTN_SIDE,   data[8] & 0x10);
			input_report_key(input, BTN_EXTRA,  data[8] & 0x08);
951
		}
952
953
		break;

954
	case 0x07:
955
	case 0x09:
956
	case 0x0b:
957
958
959
960
961
962
	case 0x0c:
	case 0x0d:
	case 0x0e:
	case 0x0f:
		/* unhandled */
		break;
963
964
	}

965
966
	input_report_abs(input, ABS_MISC,
			 wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */
967
968
	input_report_key(input, wacom->tool[idx], 1);
	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
969
	wacom->reporting_data = true;
970
	return 2;
971
972
}

973
static int wacom_intuos_irq(struct wacom_wac *wacom)
974
975
{
	unsigned char *data = wacom->data;
976
	struct input_dev *input = wacom->pen_input;
977
	int result;
978

979
	if (data[0] != WACOM_REPORT_PENABLED &&
980
981
	    data[0] != WACOM_REPORT_INTUOS_ID1 &&
	    data[0] != WACOM_REPORT_INTUOS_ID2 &&
982
	    data[0] != WACOM_REPORT_INTUOSPAD &&
983
	    data[0] != WACOM_REPORT_INTUOS_PEN &&
984
985
	    data[0] != WACOM_REPORT_CINTIQ &&
	    data[0] != WACOM_REPORT_CINTIQPAD &&
986
987
988
	    data[0] != WACOM_REPORT_INTUOS5PAD) {
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
989
990
991
                return 0;
	}

992
993
994
995
	/* process pad events */
	result = wacom_intuos_pad(wacom);
	if (result)
		return result;
996
997

	/* process in/out prox events */
998
	result = wacom_intuos_inout(wacom);
999
	if (result)
1000
		return result - 1;
1001
1002

	/* process general packets */
1003
1004
1005
	result = wacom_intuos_general(wacom);
	if (result)
		return result - 1;
1006

1007
	return 0;
1008
1009
}

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
{
	unsigned char *data = wacom_wac->data;
	struct input_dev *input;
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
	struct wacom_remote *remote = wacom->remote;
	int bat_charging, bat_percent, touch_ring_mode;
	__u32 serial;
	int i, index = -1;
	unsigned long flags;

	if (data[0] != WACOM_REPORT_REMOTE) {
		hid_dbg(wacom->hdev, "%s: received unknown report #%d",
			__func__, data[0]);
		return 0;
	}

	serial = data[3] + (data[4] << 8) + (data[5] << 16);
	wacom_wac->id[0] = PAD_DEVICE_ID;

	spin_lock_irqsave(&remote->remote_lock, flags);

	for (i = 0; i < WACOM_MAX_REMOTES; i++) {
		if (remote->remotes[i].serial == serial) {
			index = i;
			break;
		}
	}

	if (index < 0 || !remote->remotes[index].registered)
		goto out;

	input = remote->remotes[index].input;

	input_report_key(input, BTN_0, (data[9] & 0x01));
	input_report_key(input, BTN_1, (data[9] & 0x02));
	input_report_key(input, BTN_2, (data[9] & 0x04));
	input_report_key(input, BTN_3, (data[9] & 0x08));
	input_report_key(input, BTN_4, (data[9] & 0x10));
	input_report_key(input, BTN_5, (data[9] & 0x20));
	input_report_key(input, BTN_6, (data[9] & 0x40));
	input_report_key(input, BTN_7, (data[9] & 0x80));

	input_report_key(input, BTN_8, (data[10] & 0x01));
	input_report_key(input, BTN_9, (data[10] & 0x02));
	input_report_key(input, BTN_A, (data[10] & 0x04));
	input_report_key(input, BTN_B, (data[10] & 0x08));
	input_report_key(input, BTN_C, (data[10] & 0x10));
	input_report_key(input, BTN_X, (data[10] & 0x20));
	input_report_key(input, BTN_Y, (data[10] & 0x40));
	input_report_key(input, BTN_Z, (data[10] & 0x80));

	input_report_key(input, BTN_BASE, (data[11] & 0x01));
	input_report_key(input, BTN_BASE2, (data[11] & 0x02));

	if (data[12] & 0x80)
1066
		input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f) - 1);
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
	else
		input_report_abs(input, ABS_WHEEL, 0);

	bat_percent = data[7] & 0x7f;
	bat_charging = !!(data[7] & 0x80);

	if (data[9] | data[10] | (data[11] & 0x03) | data[12])
		input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
	else
		input_report_abs(input, ABS_MISC, 0);

	input_event(input, EV_MSC, MSC_SERIAL, serial);

	input_sync(input);

	/*Which mode select (LED light) is currently on?*/
	touch_ring_mode = (data[11] & 0xC0) >> 6;

	for (i = 0; i < WACOM_MAX_REMOTES; i++) {
		if (remote->remotes[i].serial == serial)
			wacom->led.groups[i].select = touch_ring_mode;
	}

1090
1091
	__wacom_notify_battery(&remote->remotes[index].battery,
				WACOM_POWER_SUPPLY_STATUS_AUTO, bat_percent,
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
				bat_charging, 1, bat_charging);

out:
	spin_unlock_irqrestore(&remote->remote_lock, flags);
	return 0;
}

static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
{
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
	unsigned char *data = wacom_wac->data;
	struct wacom_remote *remote = wacom->remote;
	struct wacom_remote_data remote_dat