xref: /linux/drivers/input/touchscreen/touchright.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24003dff4SRick Koch /*
34003dff4SRick Koch  * Touchright serial touchscreen driver
44003dff4SRick Koch  *
54003dff4SRick Koch  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
64003dff4SRick Koch  *
74003dff4SRick Koch  * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)
84003dff4SRick Koch  * Copyright (c) 2004 Vojtech Pavlik
94003dff4SRick Koch  * and Dan Streetman <ddstreet@ieee.org>
104003dff4SRick Koch  */
114003dff4SRick Koch 
124003dff4SRick Koch 
134003dff4SRick Koch #include <linux/errno.h>
144003dff4SRick Koch #include <linux/kernel.h>
154003dff4SRick Koch #include <linux/module.h>
164003dff4SRick Koch #include <linux/slab.h>
174003dff4SRick Koch #include <linux/input.h>
184003dff4SRick Koch #include <linux/serio.h>
194003dff4SRick Koch 
204003dff4SRick Koch #define DRIVER_DESC	"Touchright serial touchscreen driver"
214003dff4SRick Koch 
224003dff4SRick Koch MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
234003dff4SRick Koch MODULE_DESCRIPTION(DRIVER_DESC);
244003dff4SRick Koch MODULE_LICENSE("GPL");
254003dff4SRick Koch 
264003dff4SRick Koch /*
274003dff4SRick Koch  * Definitions & global arrays.
284003dff4SRick Koch  */
294003dff4SRick Koch 
304003dff4SRick Koch #define TR_FORMAT_TOUCH_BIT	0x01
314003dff4SRick Koch #define TR_FORMAT_STATUS_BYTE	0x40
324003dff4SRick Koch #define TR_FORMAT_STATUS_MASK	~TR_FORMAT_TOUCH_BIT
334003dff4SRick Koch 
344003dff4SRick Koch #define TR_LENGTH 5
354003dff4SRick Koch 
364003dff4SRick Koch #define TR_MIN_XC 0
374003dff4SRick Koch #define TR_MAX_XC 0x1ff
384003dff4SRick Koch #define TR_MIN_YC 0
394003dff4SRick Koch #define TR_MAX_YC 0x1ff
404003dff4SRick Koch 
414003dff4SRick Koch /*
424003dff4SRick Koch  * Per-touchscreen data.
434003dff4SRick Koch  */
444003dff4SRick Koch 
454003dff4SRick Koch struct tr {
464003dff4SRick Koch 	struct input_dev *dev;
474003dff4SRick Koch 	struct serio *serio;
484003dff4SRick Koch 	int idx;
494003dff4SRick Koch 	unsigned char data[TR_LENGTH];
504003dff4SRick Koch 	char phys[32];
514003dff4SRick Koch };
524003dff4SRick Koch 
534003dff4SRick Koch static irqreturn_t tr_interrupt(struct serio *serio,
547d12e780SDavid Howells 		unsigned char data, unsigned int flags)
554003dff4SRick Koch {
564003dff4SRick Koch 	struct tr *tr = serio_get_drvdata(serio);
574003dff4SRick Koch 	struct input_dev *dev = tr->dev;
584003dff4SRick Koch 
594003dff4SRick Koch 	tr->data[tr->idx] = data;
604003dff4SRick Koch 
614003dff4SRick Koch 	if ((tr->data[0] & TR_FORMAT_STATUS_MASK) == TR_FORMAT_STATUS_BYTE) {
624003dff4SRick Koch 		if (++tr->idx == TR_LENGTH) {
634003dff4SRick Koch 			input_report_abs(dev, ABS_X,
644003dff4SRick Koch 				(tr->data[1] << 5) | (tr->data[2] >> 1));
654003dff4SRick Koch 			input_report_abs(dev, ABS_Y,
664003dff4SRick Koch 				(tr->data[3] << 5) | (tr->data[4] >> 1));
674003dff4SRick Koch 			input_report_key(dev, BTN_TOUCH,
684003dff4SRick Koch 				tr->data[0] & TR_FORMAT_TOUCH_BIT);
694003dff4SRick Koch 			input_sync(dev);
704003dff4SRick Koch 			tr->idx = 0;
714003dff4SRick Koch 		}
724003dff4SRick Koch 	}
734003dff4SRick Koch 
744003dff4SRick Koch 	return IRQ_HANDLED;
754003dff4SRick Koch }
764003dff4SRick Koch 
774003dff4SRick Koch /*
784003dff4SRick Koch  * tr_disconnect() is the opposite of tr_connect()
794003dff4SRick Koch  */
804003dff4SRick Koch 
814003dff4SRick Koch static void tr_disconnect(struct serio *serio)
824003dff4SRick Koch {
834003dff4SRick Koch 	struct tr *tr = serio_get_drvdata(serio);
844003dff4SRick Koch 
854003dff4SRick Koch 	input_get_device(tr->dev);
864003dff4SRick Koch 	input_unregister_device(tr->dev);
874003dff4SRick Koch 	serio_close(serio);
884003dff4SRick Koch 	serio_set_drvdata(serio, NULL);
894003dff4SRick Koch 	input_put_device(tr->dev);
904003dff4SRick Koch 	kfree(tr);
914003dff4SRick Koch }
924003dff4SRick Koch 
934003dff4SRick Koch /*
944003dff4SRick Koch  * tr_connect() is the routine that is called when someone adds a
954003dff4SRick Koch  * new serio device that supports the Touchright protocol and registers it as
964003dff4SRick Koch  * an input device.
974003dff4SRick Koch  */
984003dff4SRick Koch 
994003dff4SRick Koch static int tr_connect(struct serio *serio, struct serio_driver *drv)
1004003dff4SRick Koch {
1014003dff4SRick Koch 	struct tr *tr;
1024003dff4SRick Koch 	struct input_dev *input_dev;
1034003dff4SRick Koch 	int err;
1044003dff4SRick Koch 
1054003dff4SRick Koch 	tr = kzalloc(sizeof(struct tr), GFP_KERNEL);
1064003dff4SRick Koch 	input_dev = input_allocate_device();
1074003dff4SRick Koch 	if (!tr || !input_dev) {
1084003dff4SRick Koch 		err = -ENOMEM;
1094003dff4SRick Koch 		goto fail1;
1104003dff4SRick Koch 	}
1114003dff4SRick Koch 
1124003dff4SRick Koch 	tr->serio = serio;
1134003dff4SRick Koch 	tr->dev = input_dev;
1144003dff4SRick Koch 	snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
1154003dff4SRick Koch 
1164003dff4SRick Koch 	input_dev->name = "Touchright Serial TouchScreen";
1174003dff4SRick Koch 	input_dev->phys = tr->phys;
1184003dff4SRick Koch 	input_dev->id.bustype = BUS_RS232;
1194003dff4SRick Koch 	input_dev->id.vendor = SERIO_TOUCHRIGHT;
1204003dff4SRick Koch 	input_dev->id.product = 0;
1214003dff4SRick Koch 	input_dev->id.version = 0x0100;
122a5394fb0SDmitry Torokhov 	input_dev->dev.parent = &serio->dev;
1237b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
1247b19ada2SJiri Slaby 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
1254003dff4SRick Koch 	input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0);
1264003dff4SRick Koch 	input_set_abs_params(tr->dev, ABS_Y, TR_MIN_YC, TR_MAX_YC, 0, 0);
1274003dff4SRick Koch 
1284003dff4SRick Koch 	serio_set_drvdata(serio, tr);
1294003dff4SRick Koch 
1304003dff4SRick Koch 	err = serio_open(serio, drv);
1314003dff4SRick Koch 	if (err)
1324003dff4SRick Koch 		goto fail2;
1334003dff4SRick Koch 
1344003dff4SRick Koch 	err = input_register_device(tr->dev);
1354003dff4SRick Koch 	if (err)
1364003dff4SRick Koch 		goto fail3;
1374003dff4SRick Koch 
1384003dff4SRick Koch 	return 0;
1394003dff4SRick Koch 
1404003dff4SRick Koch  fail3:	serio_close(serio);
1414003dff4SRick Koch  fail2:	serio_set_drvdata(serio, NULL);
1424003dff4SRick Koch  fail1:	input_free_device(input_dev);
1434003dff4SRick Koch 	kfree(tr);
1444003dff4SRick Koch 	return err;
1454003dff4SRick Koch }
1464003dff4SRick Koch 
1474003dff4SRick Koch /*
1484003dff4SRick Koch  * The serio driver structure.
1494003dff4SRick Koch  */
1504003dff4SRick Koch 
151ef2bc04eSArvind Yadav static const struct serio_device_id tr_serio_ids[] = {
1524003dff4SRick Koch 	{
1534003dff4SRick Koch 		.type	= SERIO_RS232,
1544003dff4SRick Koch 		.proto	= SERIO_TOUCHRIGHT,
1554003dff4SRick Koch 		.id	= SERIO_ANY,
1564003dff4SRick Koch 		.extra	= SERIO_ANY,
1574003dff4SRick Koch 	},
1584003dff4SRick Koch 	{ 0 }
1594003dff4SRick Koch };
1604003dff4SRick Koch 
1614003dff4SRick Koch MODULE_DEVICE_TABLE(serio, tr_serio_ids);
1624003dff4SRick Koch 
1634003dff4SRick Koch static struct serio_driver tr_drv = {
1644003dff4SRick Koch 	.driver		= {
1654003dff4SRick Koch 		.name	= "touchright",
1664003dff4SRick Koch 	},
1674003dff4SRick Koch 	.description	= DRIVER_DESC,
1684003dff4SRick Koch 	.id_table	= tr_serio_ids,
1694003dff4SRick Koch 	.interrupt	= tr_interrupt,
1704003dff4SRick Koch 	.connect	= tr_connect,
1714003dff4SRick Koch 	.disconnect	= tr_disconnect,
1724003dff4SRick Koch };
1734003dff4SRick Koch 
17465ac9f7aSAxel Lin module_serio_driver(tr_drv);
175