wacom_wac.c 149 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 258
static int wacom_dtus_irq(struct wacom_wac *wacom)
{
	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 545
		/* 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
		 */
546
		buttons = ((data[2] >> 4) << 7) |
547 548 549
		          ((data[1] & 0x04) << 6) |
		          ((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 580
	prox = (buttons & ~(~0 << nbuttons)) | (keys & ~(~0 << nkeys)) |
	       (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 853
	input_report_abs(input, ABS_X, x);
	input_report_abs(input, ABS_Y, y);
	input_report_abs(input, ABS_DISTANCE, distance);
854

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

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

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

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

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

922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
		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);
940
			}
941
		}
942
		else if (wacom->tool[idx] == BTN_TOOL_LENS) {
943
			/* Lens cursor packets */
944 945 946 947 948
			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);
949
		}
950 951
		break;

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

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

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

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

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

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

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

1005
	return 0;
1006 1007
}

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 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
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)
		input_report_abs(input, ABS_WHEEL, (data[12] & 0x7f));
	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;
	}

1088 1089
	__wacom_notify_battery(&remote->remotes[index].battery,
				WACOM_POWER_SUPPLY_STATUS_AUTO, bat_percent,
1090 1091 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
				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_data;
	unsigned long flags;
	int i, ret;

	if (data[0] != WACOM_REPORT_DEVICE_LIST)
		return;

	memset(&remote_data, 0, sizeof(struct wacom_remote_data));

	for (i = 0; i < WACOM_MAX_REMOTES; i++) {
		int j = i * 6;
		int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4];
		bool connected = data[j+2];

		remote_data.remote[i].serial = serial;
		remote_data.remote[i].connected = connected;
	}

	spin_lock_irqsave(&remote->remote_lock, flags);

	ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data));
	if (ret != sizeof(remote_data)) {
		spin_unlock_irqrestore(&remote->remote_lock, flags);
		hid_err(wacom->hdev, "Can't queue Remote status event.\n");
		return;
	}

	spin_unlock_irqrestore(&remote->remote_lock, flags);

	wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE);
}

1134 1135 1136 1137 1138 1139 1140 1141
static int int_dist(int x1, int y1, int x2, int y2)
{
	int x = x2 - x1;
	int y = y2 - y1;

	return int_sqrt(x*x + y*y);
}

1142 1143 1144 1145 1146 1147
static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
		unsigned char *data)
{
	memcpy(wacom->data, data, 10);
	wacom_intuos_irq(wacom);

1148
	input_sync(wacom->pen_input);
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
	if (wacom->pad_input)
		input_sync(wacom->pad_input);
}

static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
{
	unsigned char data[WACOM_PKGLEN_MAX];
	int i = 1;
	unsigned power_raw, battery_capacity, bat_charging, ps_connected;

	memcpy(data, wacom->data, len);

	switch (data[0]) {
	case 0x04:
		wacom_intuos_bt_process_data(wacom, data + i);
		i += 10;
		/* fall through */
	case 0x03:
		wacom_intuos_bt_process_data(wacom, data + i);
		i += 10;
		wacom_intuos_bt_process_data(wacom, data + i);
		i += 10;
		power_raw = data[i];
		bat_charging = (power_raw & 0x08) ? 1 : 0;
		ps_connected = (power_raw & 0x10) ? 1 : 0;
		battery_capacity = batcap_i4[power_raw & 0x07];
1175 1176
		wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
				     battery_capacity, bat_charging,
1177
				     battery_capacity || bat_charging,
1178
				     ps_connected);
1179 1180
		break;
	default:
1181
		dev_dbg(wacom->pen_input->dev.parent,
1182 1183 1184 1185 1186 1187 1188
				"Unknown report: %d,%d size:%zu\n",
				data[0], data[1], len);
		return 0;
	}
	return 0;
}

1189 1190
static int wacom_wac_finger_count_touches(struct wacom_wac *wacom)
{
1191
	struct input_dev *input = wacom->touch_input;
1192 1193 1194 1195
	unsigned touch_max = wacom->features.touch_max;
	int count = 0;
	int i;

1196 1197 1198
	if (!touch_max)
		return 0;

1199 1200
	if (touch_max == 1)
		return test_bit(BTN_TOUCH, input->key) &&
1201
			report_touch_events(wacom);
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212

	for (i = 0; i < input->mt->num_slots; i++) {
		struct input_mt_slot *ps = &input->mt->slots[i];
		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
		if (id >= 0)
			count++;
	}

	return count;
}

1213 1214
static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
{
1215
	int pen_frame_len, pen_frames;
1216 1217 1218 1219 1220

	struct input_dev *pen_input = wacom->pen_input;
	unsigned char *data = wacom->data;
	int i;

1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
	if (wacom->features.type == INTUOSP2_BT) {
		wacom->serial[0] = get_unaligned_le64(&data[99]);
		wacom->id[0]     = get_unaligned_le16(&data[107]);
		pen_frame_len = 14;
		pen_frames = 7;
	} else {
		wacom->serial[0] = get_unaligned_le64(&data[33]);
		wacom->id[0]     = get_unaligned_le16(&data[41]);
		pen_frame_len = 8;
		pen_frames = 4;
	}

1233 1234 1235 1236 1237 1238 1239 1240
	if (wacom->serial[0] >> 52 == 1) {
		/* Add back in missing bits of ID for non-USI pens */
		wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
	}
	wacom->tool[0]   = wacom_intuos_get_tool_type(wacom_intuos_id_mangle(wacom->id[0]));

	for (i = 0; i < pen_frames; i++) {
		unsigned char *frame = &data[i*pen_frame_len + 1];
1241 1242 1243
		bool valid = frame[0] & 0x80;
		bool prox = frame[0] & 0x40;
		bool range = frame[0] & 0x20;
1244

1245
		if (!valid)
1246 1247
			continue;

1248 1249 1250 1251 1252 1253
		if (!prox) {
			wacom->shared->stylus_in_proximity = false;
			wacom_exit_report(wacom);
			input_sync(pen_input);
			return;
		}
1254 1255 1256
		if (range) {
			input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
			input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274

			if (wacom->features.type == INTUOSP2_BT) {
				/* Fix rotation alignment: userspace expects zero at left */
				int16_t rotation =
					(int16_t)get_unaligned_le16(&frame[9]);
				rotation += 1800/4;

				if (rotation > 899)
					rotation -= 1800;

				input_report_abs(pen_input, ABS_TILT_X,
						 (char)frame[7]);
				input_report_abs(pen_input, ABS_TILT_Y,
						 (char)frame[8]);
				input_report_abs(pen_input, ABS_Z, rotation);
				input_report_abs(pen_input, ABS_WHEEL,
						 get_unaligned_le16(&frame[11]));
			}
1275
		}
1276
		input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
1277 1278 1279 1280 1281 1282 1283
		if (wacom->features.type == INTUOSP2_BT) {
			input_report_abs(pen_input, ABS_DISTANCE,
					 range ? frame[13] : wacom->features.distance_max);
		} else {
			input_report_abs(pen_input, ABS_DISTANCE,
					 range ? frame[7] : wacom->features.distance_max);
		}
1284 1285 1286 1287 1288

		input_report_key(pen_input, BTN_TOUCH, frame[0] & 0x01);
		input_report_key(pen_input, BTN_STYLUS, frame[0] & 0x02);
		input_report_key(pen_input, BTN_STYLUS2, frame[0] & 0x04);

1289
		input_report_key(pen_input, wacom->tool[0], prox);
1290 1291 1292 1293
		input_event(pen_input, EV_MSC, MSC_SERIAL, wacom->serial[0]);
		input_report_abs(pen_input, ABS_MISC,
				 wacom_intuos_id_mangle(wacom->id[0])); /* report tool id */

1294
		wacom->shared->stylus_in_proximity = prox;
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366

		input_sync(pen_input);
	}
}

static void wacom_intuos_pro2_bt_touch(struct wacom_wac *wacom)
{
	const int finger_touch_len = 8;
	const int finger_frames = 4;
	const int finger_frame_len = 43;

	struct input_dev *touch_input = wacom->touch_input;
	unsigned char *data = wacom->data;
	int num_contacts_left = 5;
	int i, j;

	for (i = 0; i < finger_frames; i++) {
		unsigned char *frame = &data[i*finger_frame_len + 109];
		int current_num_contacts = frame[0] & 0x7F;
		int contacts_to_send;

		if (!(frame[0] & 0x80))
			continue;

		/*
		 * First packet resets the counter since only the first
		 * packet in series will have non-zero current_num_contacts.
		 */
		if (current_num_contacts)
			wacom->num_contacts_left = current_num_contacts;

		contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);

		for (j = 0; j < contacts_to_send; j++) {
			unsigned char *touch = &frame[j*finger_touch_len + 1];
			int slot = input_mt_get_slot_by_key(touch_input, touch[0]);
			int x = get_unaligned_le16(&touch[2]);
			int y = get_unaligned_le16(&touch[4]);
			int w = touch[6] * input_abs_get_res(touch_input, ABS_MT_POSITION_X);
			int h = touch[7] * input_abs_get_res(touch_input, ABS_MT_POSITION_Y);

			if (slot < 0)
				continue;

			input_mt_slot(touch_input, slot);
			input_mt_report_slot_state(touch_input, MT_TOOL_FINGER, touch[1] & 0x01);
			input_report_abs(touch_input, ABS_MT_POSITION_X, x);
			input_report_abs(touch_input, ABS_MT_POSITION_Y, y);
			input_report_abs(touch_input, ABS_MT_TOUCH_MAJOR, max(w, h));
			input_report_abs(touch_input, ABS_MT_TOUCH_MINOR, min(w, h));
			input_report_abs(touch_input, ABS_MT_ORIENTATION, w > h);
		}

		input_mt_sync_frame(touch_input);

		wacom->num_contacts_left -= contacts_to_send;
		if (wacom->num_contacts_left <= 0) {
			wacom->num_contacts_left = 0;
			wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
		}
	}

	input_report_switch(touch_input, SW_MUTE_DEVICE, !(data[281] >> 7));
	input_sync(touch_input);
}

static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
{
	struct input_dev *pad_input = wacom->pad_input;
	unsigned char *data = wacom->data;

	int buttons = (data[282] << 1) | ((data[281] >> 6) & 0x01);
1367 1368 1369 1370 1371 1372 1373 1374 1375
	int ring = data[285] & 0x7F;
	bool ringstatus = data[285] & 0x80;
	bool prox = buttons || ringstatus;

	/* Fix touchring data: userspace expects 0 at left and increasing clockwise */
	ring = 71 - ring;
	ring += 3*72/16;
	if (ring > 71)
		ring -= 72;
1376 1377 1378

	wacom_report_numbered_buttons(pad_input, 9, buttons);

1379
	input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394

	input_report_key(pad_input, wacom->tool[1], prox ? 1 : 0);
	input_report_abs(pad_input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
	input_event(pad_input, EV_MSC, MSC_SERIAL, 0xffffffff);

	input_sync(pad_input);
}

static void wacom_intuos_pro2_bt_battery(struct wacom_wac *wacom)
{
	unsigned char *data = wacom->data;

	bool chg = data[284] & 0x80;
	int battery_status = data[284] & 0x7F;

1395 1396
	wacom_notify_battery(wacom, WACOM_POWER_SUPPLY_STATUS_AUTO,
			     battery_status, chg, 1, chg);
1397 1398
}

1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
static void wacom_intuos_gen3_bt_pad(struct wacom_wac *wacom)
{
	struct input_dev *pad_input = wacom->pad_input;
	unsigned char *data = wacom->data;

	int buttons = data[44];

	wacom_report_numbered_buttons(pad_input, 4, buttons);

	input_report_key(pad_input, wacom->tool[1], buttons ? 1 : 0);
	input_report_abs(pad_input, ABS_MISC, buttons ? PAD_DEVICE_ID : 0);
	input_event(pad_input, EV_MSC, MSC_SERIAL, 0xffffffff<