12089Ssos// SPDX-License-Identifier: GPL-2.0-or-later
216565Ssos/*
32089Ssos * Wacom protocol 4 serial tablet driver
42089Ssos *
52089Ssos * Copyright 2014      Hans de Goede <hdegoede@redhat.com>
62089Ssos * Copyright 2011-2012 Julian Squires <julian@cipht.net>
72089Ssos *
82089Ssos * Many thanks to Bill Seremetis, without whom PenPartner support
95994Ssos * would not have been possible. Thanks to Patrick Mahoney.
105994Ssos *
112089Ssos * This driver was developed with reference to much code written by others,
122089Ssos * particularly:
132089Ssos *  - elo, gunze drivers by Vojtech Pavlik <vojtech@ucw.cz>;
142089Ssos *  - wacom_w8001 driver by Jaya Kumar <jayakumar.lkml@gmail.com>;
152089Ssos *  - the USB wacom input driver, credited to many people
162089Ssos *    (see drivers/input/tablet/wacom.h);
172089Ssos *  - new and old versions of linuxwacom / xf86-input-wacom credited to
182089Ssos *    Frederic Lepied, France. <Lepied@XFree86.org> and
192089Ssos *    Ping Cheng, Wacom. <pingc@wacom.com>;
202089Ssos *  - and xf86wacom.c (a presumably ancient version of the linuxwacom code),
212089Ssos *    by Frederic Lepied and Raph Levien <raph@gtk.org>.
222089Ssos *
232089Ssos * To do:
242089Ssos *  - support pad buttons; (requires access to a model with pad buttons)
252089Ssos *  - support (protocol 4-style) tilt (requires access to a > 1.4 rom model)
262089Ssos */
272089Ssos
282089Ssos/*
2930764Scharnier * Wacom serial protocol 4 documentation taken from linuxwacom-0.9.9 code,
3030764Scharnier * protocol 4 uses 7 or 9 byte of data in the following format:
3150479Speter *
3230764Scharnier *	Byte 1
3330764Scharnier *	bit 7  Sync bit always 1
342089Ssos *	bit 6  Pointing device detected
3530764Scharnier *	bit 5  Cursor = 0 / Stylus = 1
3655849Syokota *	bit 4  Reserved
372089Ssos *	bit 3  1 if a button on the pointing device has been pressed
3823457Sbrian *	bit 2  P0 (optional)
3930764Scharnier *	bit 1  X15
4023702Speter *	bit 0  X14
412089Ssos *
422089Ssos *	Byte 2
432089Ssos *	bit 7  Always 0
4423457Sbrian *	bits 6-0 = X13 - X7
452089Ssos *
462089Ssos *	Byte 3
472089Ssos *	bit 7  Always 0
482089Ssos *	bits 6-0 = X6 - X0
492089Ssos *
502089Ssos *	Byte 4
516628Ssos *	bit 7  Always 0
522089Ssos *	bit 6  B3
536047Ssos *	bit 5  B2
542089Ssos *	bit 4  B1
552089Ssos *	bit 3  B0
562089Ssos *	bit 2  P1 (optional)
572089Ssos *	bit 1  Y15
5830764Scharnier *	bit 0  Y14
596628Ssos *
606628Ssos *	Byte 5
6155849Syokota *	bit 7  Always 0
6230764Scharnier *	bits 6-0 = Y13 - Y7
6355849Syokota *
6455849Syokota *	Byte 6
6555849Syokota *	bit 7  Always 0
6630764Scharnier *	bits 6-0 = Y6 - Y0
676628Ssos *
686628Ssos *	Byte 7
692089Ssos *	bit 7 Always 0
702089Ssos *	bit 6  Sign of pressure data; or wheel-rel for cursor tool
712089Ssos *	bit 5  P7; or REL1 for cursor tool
722089Ssos *	bit 4  P6; or REL0 for cursor tool
732089Ssos *	bit 3  P5
7430764Scharnier *	bit 2  P4
752089Ssos *	bit 1  P3
762089Ssos *	bit 0  P2
772089Ssos *
782089Ssos *	byte 8 and 9 are optional and present only
792089Ssos *	in tilt mode.
802089Ssos *
816628Ssos *	Byte 8
826628Ssos *	bit 7 Always 0
836628Ssos *	bit 6 Sign of tilt X
842089Ssos *	bit 5  Xt6
852089Ssos *	bit 4  Xt5
8652262Sbillf *	bit 3  Xt4
872089Ssos *	bit 2  Xt3
882089Ssos *	bit 1  Xt2
892089Ssos *	bit 0  Xt1
902089Ssos *
9152262Sbillf *	Byte 9
922089Ssos *	bit 7 Always 0
932089Ssos *	bit 6 Sign of tilt Y
942089Ssos *	bit 5  Yt6
952089Ssos *	bit 4  Yt5
962089Ssos *	bit 3  Yt4
972089Ssos *	bit 2  Yt3
982089Ssos *	bit 1  Yt2
992089Ssos *	bit 0  Yt1
1002089Ssos */
1012089Ssos
1022089Ssos#include <linux/completion.h>
1032089Ssos#include <linux/init.h>
1042089Ssos#include <linux/input.h>
1052089Ssos#include <linux/interrupt.h>
1062089Ssos#include <linux/kernel.h>
10723457Sbrian#include <linux/module.h>
1082089Ssos#include <linux/serio.h>
1092089Ssos#include <linux/slab.h>
1102089Ssos#include <linux/string.h>
1112089Ssos
1122089SsosMODULE_AUTHOR("Julian Squires <julian@cipht.net>, Hans de Goede <hdegoede@redhat.com>");
1132089SsosMODULE_DESCRIPTION("Wacom protocol 4 serial tablet driver");
1142089SsosMODULE_LICENSE("GPL");
1152089Ssos
11623457Sbrian#define REQUEST_MODEL_AND_ROM_VERSION	"~#"
11723457Sbrian#define REQUEST_MAX_COORDINATES		"~C\r"
1182089Ssos#define REQUEST_CONFIGURATION_STRING	"~R\r"
1192089Ssos#define REQUEST_RESET_TO_PROTOCOL_IV	"\r#"
1202089Ssos/*
12130764Scharnier * Note: sending "\r$\r" causes at least the Digitizer II to send
1222089Ssos * packets in ASCII instead of binary.  "\r#" seems to undo that.
1232089Ssos */
1242089Ssos
12523457Sbrian#define COMMAND_START_SENDING_PACKETS		"ST\r"
1262089Ssos#define COMMAND_STOP_SENDING_PACKETS		"SP\r"
1272089Ssos#define COMMAND_MULTI_MODE_INPUT		"MU1\r"
12830764Scharnier#define COMMAND_ORIGIN_IN_UPPER_LEFT		"OC1\r"
12923457Sbrian#define COMMAND_ENABLE_ALL_MACRO_BUTTONS	"~M0\r"
1302089Ssos#define COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS	"~M1\r"
1312089Ssos#define COMMAND_TRANSMIT_AT_MAX_RATE		"IT0\r"
1322089Ssos#define COMMAND_DISABLE_INCREMENTAL_MODE	"IN0\r"
1332089Ssos#define COMMAND_ENABLE_CONTINUOUS_MODE		"SR\r"
13430764Scharnier#define COMMAND_ENABLE_PRESSURE_MODE		"PH1\r"
13523457Sbrian#define COMMAND_Z_FILTER			"ZF1\r"
1362089Ssos
1372089Ssos/* Note that this is a protocol 4 packet without tilt information. */
1382089Ssos#define PACKET_LENGTH		7
1392089Ssos#define DATA_SIZE		32
1402089Ssos
1416628Ssos/* flags */
1422089Ssos#define F_COVERS_SCREEN		0x01
1432089Ssos#define F_HAS_STYLUS2		0x02
1442089Ssos#define F_HAS_SCROLLWHEEL	0x04
1452089Ssos
1462089Ssos/* device IDs */
14730764Scharnier#define STYLUS_DEVICE_ID	0x02
1482089Ssos#define CURSOR_DEVICE_ID	0x06
1492089Ssos#define ERASER_DEVICE_ID	0x0A
1502089Ssos
1512089Ssosenum { STYLUS = 1, ERASER, CURSOR };
1522089Ssos
1532089Ssosstatic const struct {
1542089Ssos	int device_id;
1552089Ssos	int input_id;
1562089Ssos} tools[] = {
15730764Scharnier	{ 0, 0 },
1582089Ssos	{ STYLUS_DEVICE_ID, BTN_TOOL_PEN },
1592089Ssos	{ ERASER_DEVICE_ID, BTN_TOOL_RUBBER },
1602089Ssos	{ CURSOR_DEVICE_ID, BTN_TOOL_MOUSE },
1612089Ssos};
1622089Ssos
1632089Ssosstruct wacom {
1648857Srgrimes	struct input_dev *dev;
1652089Ssos	struct completion cmd_done;
1662089Ssos	int result;
1672089Ssos	u8 expect;
1682089Ssos	u8 eraser_mask;
1692089Ssos	unsigned int extra_z_bits;
1702089Ssos	unsigned int flags;
1712089Ssos	unsigned int res_x, res_y;
1728857Srgrimes	unsigned int max_x, max_y;
1732089Ssos	unsigned int tool;
1742089Ssos	unsigned int idx;
17523457Sbrian	u8 data[DATA_SIZE];
17637636Sbde	char phys[32];
17737636Sbde};
1782089Ssos
1792089Ssosenum {
1802089Ssos	MODEL_CINTIQ		= 0x504C, /* PL */
1812089Ssos	MODEL_CINTIQ2		= 0x4454, /* DT */
1822089Ssos	MODEL_DIGITIZER_II	= 0x5544, /* UD */
1832089Ssos	MODEL_GRAPHIRE		= 0x4554, /* ET */
18423457Sbrian	MODEL_PENPARTNER	= 0x4354, /* CT */
18523457Sbrian	MODEL_ARTPAD_II		= 0x4B54, /* KT */
1862089Ssos};
1872089Ssos
1882089Ssosstatic void wacom_handle_model_response(struct wacom *wacom)
18930764Scharnier{
1902089Ssos	int major_v, minor_v, r = 0;
1912089Ssos	char *p;
1922089Ssos
1932089Ssos	p = strrchr(wacom->data, 'V');
1942089Ssos	if (p)
1952089Ssos		r = sscanf(p + 1, "%u.%u", &major_v, &minor_v);
1962089Ssos	if (r != 2)
1972089Ssos		major_v = minor_v = 0;
1982089Ssos
1992089Ssos	switch (wacom->data[2] << 8 | wacom->data[3]) {
2002089Ssos	case MODEL_CINTIQ:	/* UNTESTED */
2012089Ssos	case MODEL_CINTIQ2:
2022089Ssos		if ((wacom->data[2] << 8 | wacom->data[3]) == MODEL_CINTIQ) {
2032089Ssos			wacom->dev->name = "Wacom Cintiq";
2042089Ssos			wacom->dev->id.version = MODEL_CINTIQ;
20530764Scharnier		} else {
20623457Sbrian			wacom->dev->name = "Wacom Cintiq II";
2072089Ssos			wacom->dev->id.version = MODEL_CINTIQ2;
2082089Ssos		}
2092089Ssos		wacom->res_x = 508;
2102089Ssos		wacom->res_y = 508;
2112089Ssos
2122089Ssos		switch (wacom->data[5] << 8 | wacom->data[6]) {
21330764Scharnier		case 0x3731: /* PL-710 */
21423457Sbrian			wacom->res_x = 2540;
2152089Ssos			wacom->res_y = 2540;
2162089Ssos			fallthrough;
2172089Ssos		case 0x3535: /* PL-550 */
2182089Ssos		case 0x3830: /* PL-800 */
2192089Ssos			wacom->extra_z_bits = 2;
22030764Scharnier		}
22123457Sbrian
2222089Ssos		wacom->flags = F_COVERS_SCREEN;
2232089Ssos		break;
2242089Ssos
2252089Ssos	case MODEL_PENPARTNER:
2262089Ssos		wacom->dev->name = "Wacom Penpartner";
2272089Ssos		wacom->dev->id.version = MODEL_PENPARTNER;
2282089Ssos		wacom->res_x = 1000;
2292089Ssos		wacom->res_y = 1000;
2302089Ssos		break;
2312089Ssos
2322089Ssos	case MODEL_GRAPHIRE:
2332089Ssos		wacom->dev->name = "Wacom Graphire";
2342089Ssos		wacom->dev->id.version = MODEL_GRAPHIRE;
23530764Scharnier		wacom->res_x = 1016;
2362089Ssos		wacom->res_y = 1016;
2372089Ssos		wacom->max_x = 5103;
2382089Ssos		wacom->max_y = 3711;
2392089Ssos		wacom->extra_z_bits = 2;
24030764Scharnier		wacom->eraser_mask = 0x08;
2412089Ssos		wacom->flags = F_HAS_STYLUS2 | F_HAS_SCROLLWHEEL;
2422089Ssos		break;
2432089Ssos
2445536Ssos	case MODEL_ARTPAD_II:
2452089Ssos	case MODEL_DIGITIZER_II:
2465536Ssos		wacom->dev->name = "Wacom Digitizer II";
2472089Ssos		wacom->dev->id.version = MODEL_DIGITIZER_II;
2486230Ssos		if (major_v == 1 && minor_v <= 2)
2496230Ssos			wacom->extra_z_bits = 0; /* UNTESTED */
2506230Ssos		break;
2515536Ssos
2526230Ssos	default:
2536230Ssos		dev_err(&wacom->dev->dev, "Unsupported Wacom model %s\n",
2545536Ssos			wacom->data);
25530764Scharnier		wacom->result = -ENODEV;
2562089Ssos		return;
2572089Ssos	}
2585536Ssos
2592089Ssos	dev_info(&wacom->dev->dev, "%s tablet, version %u.%u\n",
2602089Ssos		 wacom->dev->name, major_v, minor_v);
26123457Sbrian}
2622089Ssos
2632089Ssosstatic void wacom_handle_configuration_response(struct wacom *wacom)
26439592Syokota{
26539592Syokota	int r, skip;
26639592Syokota
26739592Syokota	dev_dbg(&wacom->dev->dev, "Configuration string: %s\n", wacom->data);
26839592Syokota	r = sscanf(wacom->data, "~R%x,%u,%u,%u,%u", &skip, &skip, &skip,
26939592Syokota		   &wacom->res_x, &wacom->res_y);
27039592Syokota	if (r != 5)
27139592Syokota		dev_warn(&wacom->dev->dev, "could not get resolution\n");
27239592Syokota}
27339592Syokota
27439592Syokotastatic void wacom_handle_coordinates_response(struct wacom *wacom)
27539592Syokota{
27639592Syokota	int r;
27739592Syokota
27839592Syokota	dev_dbg(&wacom->dev->dev, "Coordinates string: %s\n", wacom->data);
27939592Syokota	r = sscanf(wacom->data, "~C%u,%u", &wacom->max_x, &wacom->max_y);
28039592Syokota	if (r != 2)
28139592Syokota		dev_warn(&wacom->dev->dev, "could not get max coordinates\n");
28239592Syokota}
28348105Syokota
28448105Syokotastatic void wacom_handle_response(struct wacom *wacom)
28548105Syokota{
28648105Syokota	if (wacom->data[0] != '~' || wacom->data[1] != wacom->expect) {
28748105Syokota		dev_err(&wacom->dev->dev,
28848105Syokota			"Wacom got an unexpected response: %s\n", wacom->data);
28948105Syokota		wacom->result = -EIO;
29039592Syokota	} else {
29139592Syokota		wacom->result = 0;
29239592Syokota
29339592Syokota		switch (wacom->data[1]) {
29439592Syokota		case '#':
29539592Syokota			wacom_handle_model_response(wacom);
29639592Syokota			break;
29739592Syokota		case 'R':
29839592Syokota			wacom_handle_configuration_response(wacom);
29939592Syokota			break;
30042605Smjacob		case 'C':
30148105Syokota			wacom_handle_coordinates_response(wacom);
30248105Syokota			break;
30339287Ssos		}
30439592Syokota	}
3052089Ssos
30648105Syokota	complete(&wacom->cmd_done);
30748105Syokota}
3082089Ssos
30939592Syokotastatic void wacom_handle_packet(struct wacom *wacom)
31039592Syokota{
31139592Syokota	u8 in_proximity_p, stylus_p, button;
31239592Syokota	unsigned int tool;
31339592Syokota	int x, y, z;
31439592Syokota
31539592Syokota	in_proximity_p = wacom->data[0] & 0x40;
3162089Ssos	stylus_p = wacom->data[0] & 0x20;
3172089Ssos	button = (wacom->data[3] & 0x78) >> 3;
31830764Scharnier	x = (wacom->data[0] & 3) << 14 | wacom->data[1]<<7 | wacom->data[2];
31939287Ssos	y = (wacom->data[3] & 3) << 14 | wacom->data[4]<<7 | wacom->data[5];
32039287Ssos
32139287Ssos	if (in_proximity_p && stylus_p) {
32239287Ssos		z = wacom->data[6] & 0x7f;
32348105Syokota		if (wacom->extra_z_bits >= 1)
32448105Syokota			z = z << 1 | (wacom->data[3] & 0x4) >> 2;
32548105Syokota		if (wacom->extra_z_bits > 1)
32648105Syokota			z = z << 1 | (wacom->data[0] & 0x4) >> 2;
32748105Syokota		z = z ^ (0x40 << wacom->extra_z_bits);
32848105Syokota	} else {
32948105Syokota		z = -1;
33048105Syokota	}
33139287Ssos
3322089Ssos	if (stylus_p)
3332089Ssos		tool = (button & wacom->eraser_mask) ? ERASER : STYLUS;
3342089Ssos	else
3352089Ssos		tool = CURSOR;
3368857Srgrimes
3372089Ssos	if (tool != wacom->tool && wacom->tool != 0) {
3382089Ssos		input_report_key(wacom->dev, tools[wacom->tool].input_id, 0);
3392089Ssos		input_sync(wacom->dev);
3402089Ssos	}
3412089Ssos	wacom->tool = tool;
3422089Ssos
3432089Ssos	input_report_key(wacom->dev, tools[tool].input_id, in_proximity_p);
3442089Ssos	input_report_abs(wacom->dev, ABS_MISC,
3452089Ssos			 in_proximity_p ? tools[tool].device_id : 0);
3462089Ssos	input_report_abs(wacom->dev, ABS_X, x);
3472089Ssos	input_report_abs(wacom->dev, ABS_Y, y);
34823457Sbrian	input_report_abs(wacom->dev, ABS_PRESSURE, z);
3492089Ssos	if (stylus_p) {
3502089Ssos		input_report_key(wacom->dev, BTN_TOUCH, button & 1);
3512089Ssos		input_report_key(wacom->dev, BTN_STYLUS, button & 2);
3522089Ssos		input_report_key(wacom->dev, BTN_STYLUS2, button & 4);
3532089Ssos	} else {
3542089Ssos		input_report_key(wacom->dev, BTN_LEFT, button & 1);
3552089Ssos		input_report_key(wacom->dev, BTN_RIGHT, button & 2);
3568857Srgrimes		input_report_key(wacom->dev, BTN_MIDDLE, button & 4);
3578857Srgrimes		/* handle relative wheel for non-stylus device */
3582089Ssos		z = (wacom->data[6] & 0x30) >> 4;
3592089Ssos		if (wacom->data[6] & 0x40)
3602089Ssos			z = -z;
3612089Ssos		input_report_rel(wacom->dev, REL_WHEEL, z);
3622089Ssos	}
3632089Ssos	input_sync(wacom->dev);
3642089Ssos}
36523457Sbrian
3662089Ssosstatic void wacom_clear_data_buf(struct wacom *wacom)
3672089Ssos{
3682089Ssos	memset(wacom->data, 0, DATA_SIZE);
3692089Ssos	wacom->idx = 0;
3702089Ssos}
3712089Ssos
3728857Srgrimesstatic irqreturn_t wacom_interrupt(struct serio *serio, unsigned char data,
3738857Srgrimes				   unsigned int flags)
3742089Ssos{
3752089Ssos	struct wacom *wacom = serio_get_drvdata(serio);
3762089Ssos
3772089Ssos	if (data & 0x80)
3782089Ssos		wacom->idx = 0;
3792089Ssos
3802089Ssos	/*
38123457Sbrian	 * We're either expecting a carriage return-terminated ASCII
38223457Sbrian	 * response string, or a seven-byte packet with the MSB set on
38323457Sbrian	 * the first byte.
38423457Sbrian	 *
38523457Sbrian	 * Note however that some tablets (the PenPartner, for
38623457Sbrian	 * example) don't send a carriage return at the end of a
38730764Scharnier	 * command.  We handle these by waiting for timeout.
38823457Sbrian	 */
38923457Sbrian	if (data == '\r' && !(wacom->data[0] & 0x80)) {
39023457Sbrian		wacom_handle_response(wacom);
39123457Sbrian		wacom_clear_data_buf(wacom);
39251393Syokota		return IRQ_HANDLED;
39330764Scharnier	}
39442605Smjacob
39530764Scharnier	/* Leave place for 0 termination */
39623457Sbrian	if (wacom->idx > (DATA_SIZE - 2)) {
39723457Sbrian		dev_dbg(&wacom->dev->dev,
39823457Sbrian			"throwing away %d bytes of garbage\n", wacom->idx);
3992089Ssos		wacom_clear_data_buf(wacom);
4002089Ssos	}
4012089Ssos	wacom->data[wacom->idx++] = data;
4022089Ssos
4032089Ssos	if (wacom->idx == PACKET_LENGTH && (wacom->data[0] & 0x80)) {
4042089Ssos		wacom_handle_packet(wacom);
4052089Ssos		wacom_clear_data_buf(wacom);
4062089Ssos	}
4078857Srgrimes
4082089Ssos	return IRQ_HANDLED;
4092089Ssos}
41016565Ssos
41155849Syokotastatic void wacom_disconnect(struct serio *serio)
41255849Syokota{
41355849Syokota	struct wacom *wacom = serio_get_drvdata(serio);
41455849Syokota
41555849Syokota	serio_close(serio);
41655849Syokota	serio_set_drvdata(serio, NULL);
41755849Syokota	input_unregister_device(wacom->dev);
41855849Syokota	kfree(wacom);
41955849Syokota}
42055849Syokota
42155849Syokotastatic int wacom_send(struct serio *serio, const u8 *command)
42255849Syokota{
42355849Syokota	int err = 0;
42455849Syokota
42555849Syokota	for (; !err && *command; command++)
42655849Syokota		err = serio_write(serio, *command);
42716565Ssos
42816565Ssos	return err;
42916565Ssos}
43016565Ssos
43116565Ssosstatic int wacom_send_setup_string(struct wacom *wacom, struct serio *serio)
43216565Ssos{
43316565Ssos	const u8 *cmd;
43416565Ssos
43516565Ssos	switch (wacom->dev->id.version) {
43630764Scharnier	case MODEL_CINTIQ:	/* UNTESTED */
43716565Ssos		cmd = COMMAND_ORIGIN_IN_UPPER_LEFT
43816565Ssos			COMMAND_TRANSMIT_AT_MAX_RATE
43916565Ssos			COMMAND_ENABLE_CONTINUOUS_MODE
44016565Ssos			COMMAND_START_SENDING_PACKETS;
44116565Ssos		break;
44239287Ssos
44339287Ssos	case MODEL_PENPARTNER:
44439287Ssos		cmd = COMMAND_ENABLE_PRESSURE_MODE
44539287Ssos			COMMAND_START_SENDING_PACKETS;
44639287Ssos		break;
44739287Ssos
44839287Ssos	default:
44939287Ssos		cmd = COMMAND_MULTI_MODE_INPUT
45039287Ssos			COMMAND_ORIGIN_IN_UPPER_LEFT
45139287Ssos			COMMAND_ENABLE_ALL_MACRO_BUTTONS
45239287Ssos			COMMAND_DISABLE_GROUP_1_MACRO_BUTTONS
45339287Ssos			COMMAND_TRANSMIT_AT_MAX_RATE
45439287Ssos			COMMAND_DISABLE_INCREMENTAL_MODE
45548105Syokota			COMMAND_ENABLE_CONTINUOUS_MODE
45639287Ssos			COMMAND_Z_FILTER
45739287Ssos			COMMAND_START_SENDING_PACKETS;
45839287Ssos		break;
45939287Ssos	}
46039287Ssos
46139287Ssos	return wacom_send(serio, cmd);
46239287Ssos}
46339287Ssos
46439287Ssosstatic int wacom_send_and_wait(struct wacom *wacom, struct serio *serio,
46539287Ssos			       const u8 *cmd, const char *desc)
46623457Sbrian{
46739287Ssos	int err;
46839287Ssos	unsigned long u;
46942505Syokota
47039287Ssos	wacom->expect = cmd[1];
47139287Ssos	init_completion(&wacom->cmd_done);
47239287Ssos
47339287Ssos	err = wacom_send(serio, cmd);
47439287Ssos	if (err)
47539287Ssos		return err;
47639287Ssos
47742505Syokota	u = wait_for_completion_timeout(&wacom->cmd_done, HZ);
47842505Syokota	if (u == 0) {
47942505Syokota		/* Timeout, process what we've received. */
48039287Ssos		wacom_handle_response(wacom);
48142505Syokota	}
48239287Ssos
48339287Ssos	wacom->expect = 0;
48448105Syokota	return wacom->result;
48548105Syokota}
48648105Syokota
48748105Syokotastatic int wacom_setup(struct wacom *wacom, struct serio *serio)
48848105Syokota{
48948105Syokota	int err;
49048105Syokota
49139287Ssos	/* Note that setting the link speed is the job of inputattach.
49239287Ssos	 * We assume that reset negotiation has already happened,
49339287Ssos	 * here. */
49439287Ssos	err = wacom_send_and_wait(wacom, serio, REQUEST_MODEL_AND_ROM_VERSION,
49539287Ssos				  "model and version");
49639287Ssos	if (err)
49739287Ssos		return err;
49839287Ssos
49939287Ssos	if (!(wacom->res_x && wacom->res_y)) {
50039287Ssos		err = wacom_send_and_wait(wacom, serio,
50139287Ssos					  REQUEST_CONFIGURATION_STRING,
50239287Ssos					  "configuration string");
50339287Ssos		if (err)
50439287Ssos			return err;
50539287Ssos	}
50639287Ssos
50739287Ssos	if (!(wacom->max_x && wacom->max_y)) {
50839287Ssos		err = wacom_send_and_wait(wacom, serio,
50948105Syokota					  REQUEST_MAX_COORDINATES,
51048105Syokota					  "coordinates string");
51139287Ssos		if (err)
51239287Ssos			return err;
51339287Ssos	}
51439287Ssos
51539287Ssos	return wacom_send_setup_string(wacom, serio);
51639287Ssos}
51739287Ssos
51839287Ssosstatic int wacom_connect(struct serio *serio, struct serio_driver *drv)
51939287Ssos{
52039287Ssos	struct wacom *wacom;
52139287Ssos	struct input_dev *input_dev;
52239287Ssos	int err = -ENOMEM;
52339287Ssos
52439287Ssos	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
52539287Ssos	input_dev = input_allocate_device();
52639287Ssos	if (!wacom || !input_dev)
52739287Ssos		goto free_device;
52839287Ssos
52943186Sdfr	wacom->dev = input_dev;
53043186Sdfr	wacom->extra_z_bits = 1;
53148105Syokota	wacom->eraser_mask = 0x04;
53243186Sdfr	wacom->tool = wacom->idx = 0;
53339287Ssos	snprintf(wacom->phys, sizeof(wacom->phys), "%s/input0", serio->phys);
53439287Ssos	input_dev->phys = wacom->phys;
53539287Ssos	input_dev->id.bustype = BUS_RS232;
53639287Ssos	input_dev->id.vendor  = SERIO_WACOM_IV;
53739287Ssos	input_dev->id.product = serio->id.extra;
53839287Ssos	input_dev->dev.parent = &serio->dev;
53939287Ssos
54039287Ssos	input_dev->evbit[0] =
54139287Ssos		BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_REL);
54239287Ssos	set_bit(ABS_MISC, input_dev->absbit);
54339287Ssos	set_bit(BTN_TOOL_PEN, input_dev->keybit);
54439287Ssos	set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
54539287Ssos	set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
54639287Ssos	set_bit(BTN_TOUCH, input_dev->keybit);
54739287Ssos	set_bit(BTN_STYLUS, input_dev->keybit);
54839287Ssos	set_bit(BTN_LEFT, input_dev->keybit);
54939287Ssos	set_bit(BTN_RIGHT, input_dev->keybit);
5502089Ssos	set_bit(BTN_MIDDLE, input_dev->keybit);
5512089Ssos
5522089Ssos	serio_set_drvdata(serio, wacom);
5532089Ssos
5542089Ssos	err = serio_open(serio, drv);
5552089Ssos	if (err)
5562089Ssos		goto free_device;
5572089Ssos
5582089Ssos	err = wacom_setup(wacom, serio);
5598857Srgrimes	if (err)
5608857Srgrimes		goto close_serio;
5612089Ssos
5622089Ssos	set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
5638857Srgrimes	if (!(wacom->flags & F_COVERS_SCREEN))
5642089Ssos		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
5652089Ssos
5662089Ssos	if (wacom->flags & F_HAS_STYLUS2)
56723457Sbrian		__set_bit(BTN_STYLUS2, input_dev->keybit);
5682089Ssos
5692089Ssos	if (wacom->flags & F_HAS_SCROLLWHEEL)
5702089Ssos		__set_bit(REL_WHEEL, input_dev->relbit);
5712089Ssos
5728857Srgrimes	input_abs_set_res(wacom->dev, ABS_X, wacom->res_x);
5732089Ssos	input_abs_set_res(wacom->dev, ABS_Y, wacom->res_y);
57430764Scharnier	input_set_abs_params(wacom->dev, ABS_X, 0, wacom->max_x, 0, 0);
57530764Scharnier	input_set_abs_params(wacom->dev, ABS_Y, 0, wacom->max_y, 0, 0);
57655849Syokota	input_set_abs_params(wacom->dev, ABS_PRESSURE, -1,
5772089Ssos			     (1 << (7 + wacom->extra_z_bits)) - 1, 0, 0);
57816565Ssos
57916565Ssos	err = input_register_device(wacom->dev);
58016565Ssos	if (err)
5812089Ssos		goto close_serio;
5825536Ssos
5832089Ssos	return 0;
5842089Ssos
5852089Ssosclose_serio:
5862089Ssos	serio_close(serio);
5872089Ssosfree_device:
5882089Ssos	serio_set_drvdata(serio, NULL);
5892089Ssos	input_free_device(input_dev);
5902089Ssos	kfree(wacom);
59139287Ssos	return err;
59239287Ssos}
59339287Ssos
5942089Ssosstatic const struct serio_device_id wacom_serio_ids[] = {
5952089Ssos	{
5962089Ssos		.type	= SERIO_RS232,
5972089Ssos		.proto	= SERIO_WACOM_IV,
5982089Ssos		.id	= SERIO_ANY,
5992089Ssos		.extra	= SERIO_ANY,
60055849Syokota	},
60155849Syokota	{ 0 }
60255849Syokota};
60316565Ssos
60416565SsosMODULE_DEVICE_TABLE(serio, wacom_serio_ids);
60516565Ssos
6062089Ssosstatic struct serio_driver wacom_drv = {
6072089Ssos	.driver		= {
6082089Ssos		.name	= "wacom_serial4",
60923457Sbrian	},
61023457Sbrian	.description	= "Wacom protocol 4 serial tablet driver",
61123457Sbrian	.id_table	= wacom_serio_ids,
6122089Ssos	.interrupt	= wacom_interrupt,
6132089Ssos	.connect	= wacom_connect,
6142089Ssos	.disconnect	= wacom_disconnect,
6152089Ssos};
6162089Ssos
6172089Ssosmodule_serio_driver(wacom_drv);
6182089Ssos