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