wacom_wac.c 149 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * drivers/input/tablet/wacom_wac.c
4
 *
5
 *  USB Wacom tablet support - Wacom specific code
6 7 8 9
 */

/*
 */
10

11
#include "wacom_wac.h"
12
#include "wacom.h"
13
#include <linux/input/mt.h>
14

15 16 17 18 19 20 21 22
/* 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

23 24 25 26
/* Newer Cintiq and DTU have an offset between tablet and screen areas */
#define WACOM_DTU_OFFSET	200
#define WACOM_CINTIQ_OFFSET	400

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

33 34 35 36
static bool touch_arbitration = 1;
module_param(touch_arbitration, bool, 0644);
MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)");

37 38 39
static void wacom_report_numbered_buttons(struct input_dev *input_dev,
				int button_count, int mask);

40 41
static int wacom_numbered_button_to_key(int n);

42 43
static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
			     int group);
44 45 46 47 48 49
/*
 * 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 };

50 51 52 53 54
/*
 * 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 };

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

	if (changed) {
67
		battery->bat_status = bat_status;
68 69 70 71 72 73 74 75 76 77
		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);
	}
}

78
static void wacom_notify_battery(struct wacom_wac *wacom_wac,
79 80
	int bat_status, int bat_capacity, bool bat_charging,
	bool bat_connected, bool ps_connected)
81 82 83
{
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);

84 85
	__wacom_notify_battery(&wacom->battery, bat_status, bat_capacity,
			       bat_charging, bat_connected, ps_connected);
86 87
}

88
static int wacom_penpartner_irq(struct wacom_wac *wacom)
89 90
{
	unsigned char *data = wacom->data;
91
	struct input_dev *input = wacom->pen_input;
92 93

	switch (data[0]) {
94 95 96 97
	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;
98 99
			input_report_key(input, wacom->tool[0], 1);
			input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
100 101
			input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
			input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
102 103 104
			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));
105
		} else {
106 107 108 109
			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);
110 111
		}
		break;
112

113
	case 2:
114 115
		input_report_key(input, BTN_TOOL_PEN, 1);
		input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
116 117
		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
118 119 120
		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));
121
		break;
122

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

129 130 131
	return 1;
}

132
static int wacom_pl_irq(struct wacom_wac *wacom)
133
{
134
	struct wacom_features *features = &wacom->features;
135
	unsigned char *data = wacom->data;
136
	struct input_dev *input = wacom->pen_input;
137
	int prox, pressure;
138

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

	prox = data[1] & 0x40;

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

158 159 160 161 162 163 164 165 166 167
	/* 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;
168 169
	}

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
	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));
	}
185 186 187 188 189

	if (!prox)
		wacom->id[0] = 0;
	input_report_key(input, wacom->tool[0], prox);
	input_report_abs(input, ABS_MISC, wacom->id[0]);
190 191 192
	return 1;
}

193
static int wacom_ptu_irq(struct wacom_wac *wacom)
194 195
{
	unsigned char *data = wacom->data;
196
	struct input_dev *input = wacom->pen_input;
197

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

	if (data[1] & 0x04) {
205 206
		input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20);
		input_report_key(input, BTN_TOUCH, data[1] & 0x08);
207
		wacom->id[0] = ERASER_DEVICE_ID;
208
	} else {
209 210
		input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20);
		input_report_key(input, BTN_TOUCH, data[1] & 0x01);
211
		wacom->id[0] = STYLUS_DEVICE_ID;
212
	}
213
	input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */
214 215 216
	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]));
217 218
	input_report_key(input, BTN_STYLUS, data[1] & 0x02);
	input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
219 220 221
	return 1;
}

222 223
static int wacom_dtu_irq(struct wacom_wac *wacom)
{
224
	unsigned char *data = wacom->data;
225
	struct input_dev *input = wacom->pen_input;
226
	int prox = data[1] & 0x20;
227

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

	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]));
243
	input_report_abs(input, ABS_PRESSURE, ((data[7] & 0x01) << 8) | data[6]);
244 245 246 247 248 249 250 251
	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;
}

252 253 254
static int wacom_dtus_irq(struct wacom_wac *wacom)
{
	char *data = wacom->data;
255
	struct input_dev *input = wacom->pen_input;
256 257 258 259 260 261 262
	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) {
263
		input = wacom->pad_input;
264 265 266 267 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
		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;
	}
}

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

314 315 316 317 318 319 320 321
	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) {
322 323
		dev_dbg(input->dev.parent,
			"%s: received unknown report #%d\n", __func__, data[0]);
324
		goto exit;
325 326
	}

327 328 329 330
	prox = data[1] & 0x80;
	if (prox || wacom->id[0]) {
		if (prox) {
			switch ((data[1] >> 5) & 3) {
331 332 333

			case 0:	/* Pen */
				wacom->tool[0] = BTN_TOOL_PEN;
334
				wacom->id[0] = STYLUS_DEVICE_ID;
335 336 337 338
				break;

			case 1: /* Rubber */
				wacom->tool[0] = BTN_TOOL_RUBBER;
339
				wacom->id[0] = ERASER_DEVICE_ID;
340 341 342
				break;

			case 2: /* Mouse with wheel */
343
				input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
344 345 346 347
				/* fall through */

			case 3: /* Mouse without wheel */
				wacom->tool[0] = BTN_TOOL_MOUSE;
348
				wacom->id[0] = CURSOR_DEVICE_ID;
349
				break;
350
			}
351
		}
352 353
		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
		input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
354
		if (wacom->tool[0] != BTN_TOOL_MOUSE) {
355 356 357 358 359 360
			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));
361 362 363
			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);
364
		} else {
365 366
			input_report_key(input, BTN_LEFT, data[1] & 0x01);
			input_report_key(input, BTN_RIGHT, data[1] & 0x02);
367 368
			if (features->type == WACOM_G4 ||
					features->type == WACOM_MO) {
369
				input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f);
370
				rw = (data[7] & 0x04) - (data[7] & 0x03);
371 372 373 374 375 376 377 378 379 380 381 382 383 384
			} 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;
				}
385
			} else {
386
				input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f);
387
				rw = -(signed char)data[6];
388
			}
389
			input_report_rel(input, REL_WHEEL, rw);
390
		}
391 392 393

		if (!prox)
			wacom->id[0] = 0;
394 395 396
		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
397
	}
398 399

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

	case WACOM_MO:
417 418
		prox = (data[7] & 0xf8) || data[8];
		if (prox || wacom->id[1]) {
419
			wacom->id[1] = PAD_DEVICE_ID;
420 421 422 423 424
			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));
425 426
			if (!prox)
				wacom->id[1] = 0;
427
			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
428
			retval = 1;
429 430
		}
		break;
431 432 433 434 435 436
	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));
437 438
			if (!prox)
				wacom->id[1] = 0;
439
			input_report_abs(pad_input, ABS_MISC, wacom->id[1]);
440
			retval = 1;
441 442
		}
		break;
443
	}
444 445 446 447 448 449

	/* 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;
450 451 452
		wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
				     battery_capacity, ps_connected, 1,
				     ps_connected);
453
	}
454 455
exit:
	return retval;
456 457
}

458 459 460
static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
{
	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
461
	struct wacom_features *features = &wacom_wac->features;
462 463 464 465
	struct hid_report *r;
	struct hid_report_enum *re;

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

475 476 477 478 479
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;
480 481 482 483 484 485
	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;
486 487 488 489 490 491 492

	/* 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) {
493 494
		buttons = (data[3] << 1) | (data[2] & 0x01);
		ring1 = data[1];
495
	} else if (features->type == DTK) {
496
		buttons = data[6];
497
	} else if (features->type == WACOM_13HD) {
498
		buttons = (data[4] << 1) | (data[3] & 0x01);
499
	} else if (features->type == WACOM_24HD) {
500 501 502
		buttons = (data[8] << 8) | data[6];
		ring1 = data[1];
		ring2 = data[2];
503 504 505 506 507 508 509 510

		/*
		 * 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])
		 */
511 512 513 514
		nkeys = 3;
		keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
		       ((data[4] & 0xE0) ? 1<<1 : 0) |
		       ((data[4] & 0x07) ? 1<<0 : 0);
515
	} else if (features->type == WACOM_27QHD) {
516 517
		nkeys = 3;
		keys = data[2] & 0x07;
518 519 520 521 522 523 524 525 526

		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).
527 528 529 530 531 532
		 *
		 * 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
533
		 */
534
		buttons = (data[4] << 1) | (data[3] & 0x01);
535
	} else if (features->type == CINTIQ_COMPANION_2) {
536 537 538 539 540 541
		/* 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
		 */
542
		buttons = ((data[2] >> 4) << 7) |
543 544 545
		          ((data[1] & 0x04) << 6) |
		          ((data[2] & 0x0F) << 2) |
		          (data[1] & 0x03);
546 547 548 549 550
	} 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].
551 552
		 *
		 * Touch ring mode switch (data[3]) has no capacitive sensor
553
		 */
554 555
		buttons = (data[4] << 1) | (data[3] & 0x01);
		ring1 = data[2];
556 557
	} else {
		if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
558 559
			buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
			          (data[6] << 1) | (data[5] & 0x01);
560 561

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

575 576
	prox = (buttons & ~(~0 << nbuttons)) | (keys & ~(~0 << nkeys)) |
	       (ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2;
577 578 579 580 581 582 583

	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);
584
	input_report_abs(input, ABS_RY, strip2);
585

586 587
	input_report_abs(input, ABS_WHEEL,    (ring1 & 0x80) ? (ring1 & 0x7f) : 0);
	input_report_abs(input, ABS_THROTTLE, (ring2 & 0x80) ? (ring2 & 0x7f) : 0);
588 589 590 591 592 593

	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);

594 595 596
	return 1;
}

597 598 599 600 601
static int wacom_intuos_id_mangle(int tool_id)
{
	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
}

602 603 604 605 606 607 608
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 */
609
	case 0x12802: /* Intuos4/5 Inking Pen */
610 611 612 613 614 615 616 617 618 619 620 621 622 623
	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:
624
	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
625
	case 0x10842: /* MobileStudio Pro Pro Pen slim */
626 627 628 629
	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 */
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
		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 */
653
	case 0x84a:
654 655 656 657 658 659 660 661 662 663
	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 */
664 665 666
	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 */
667
	case 0x1084a: /* MobileStudio Pro Pro Pen slim Eraser */
668 669 670
	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
	case 0x1880a: /* DTH2242 Eraser */
	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
671 672 673 674 675 676 677 678
		tool_type = BTN_TOOL_RUBBER;
		break;

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

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

690 691 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
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;
}

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

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

	/* 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);

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

751 752
		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);

753
		wacom->shared->stylus_in_proximity = true;
754 755 756
		return 1;
	}

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

762 763 764 765 766 767 768 769
		/* 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;
770 771
	}

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

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

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

785 786 787
	return 0;
}

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

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

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

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

811
	if (delay_pen_events(wacom))
812 813
		return 1;

814 815 816 817 818 819 820
	/* 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;
	}

821 822 823 824
	/*
	 * don't report events for invalid data
	 */
	/* older I4 styli don't work with new Cintiqs */
825
	if ((!((wacom->id[idx] >> 16) & 0x01) &&
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
			(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;

841 842 843 844 845 846 847
	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;
848
	}
849 850 851
	input_report_abs(input, ABS_X, x);
	input_report_abs(input, ABS_Y, y);
	input_report_abs(input, ABS_DISTANCE, distance);
852

853 854 855 856 857 858
	switch (type) {
	case 0x00:
	case 0x01:
	case 0x02:
	case 0x03:
		/* general pen packet */
859 860 861
		t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1);
		if (features->pressure_max < 2047)
			t >>= 1;
862
		input_report_abs(input, ABS_PRESSURE, t);
863 864
		if (features->type != INTUOSHT2) {
		    input_report_abs(input, ABS_TILT_X,
865
				 (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
866 867
		    input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
		}
868 869 870
		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);
871
		break;
872

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

882 883 884 885 886 887 888 889 890
	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 {
891
			/* 4D mouse 2nd packet */
892 893 894 895 896
			t = (data[6] << 3) | ((data[7] >> 5) & 7);
			input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
				((t - 1) / 2) : -t / 2);
		}
		break;
897

898
	case 0x04:
899 900 901 902 903 904 905 906 907 908 909
		/* 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;

910
	case 0x06:
911 912 913 914 915 916 917 918
		/* 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);
919

920 921 922 923 924 925 926 927 928 929 930 931 932 933 934