1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Touchwindow serial touchscreen driver 4 * 5 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> 6 * 7 * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c) 8 * Copyright (c) 2004 Vojtech Pavlik 9 * and Dan Streetman <ddstreet@ieee.org> 10 */ 11 12 13 /* 14 * 2005/02/19 Rick Koch: 15 * The Touchwindow I used is made by Edmark Corp. and 16 * constantly outputs a stream of 0's unless it is touched. 17 * It then outputs 3 bytes: X, Y, and a copy of Y. 18 */ 19 20 #include <linux/errno.h> 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/slab.h> 24 #include <linux/input.h> 25 #include <linux/serio.h> 26 27 #define DRIVER_DESC "Touchwindow serial touchscreen driver" 28 29 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); 30 MODULE_DESCRIPTION(DRIVER_DESC); 31 MODULE_LICENSE("GPL"); 32 33 /* 34 * Definitions & global arrays. 35 */ 36 37 #define TW_LENGTH 3 38 39 #define TW_MIN_XC 0 40 #define TW_MAX_XC 0xff 41 #define TW_MIN_YC 0 42 #define TW_MAX_YC 0xff 43 44 /* 45 * Per-touchscreen data. 46 */ 47 48 struct tw { 49 struct input_dev *dev; 50 struct serio *serio; 51 int idx; 52 int touched; 53 unsigned char data[TW_LENGTH]; 54 char phys[32]; 55 }; 56 57 static irqreturn_t tw_interrupt(struct serio *serio, 58 unsigned char data, unsigned int flags) 59 { 60 struct tw *tw = serio_get_drvdata(serio); 61 struct input_dev *dev = tw->dev; 62 63 if (data) { /* touch */ 64 tw->touched = 1; 65 tw->data[tw->idx++] = data; 66 /* verify length and that the two Y's are the same */ 67 if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) { 68 input_report_abs(dev, ABS_X, tw->data[0]); 69 input_report_abs(dev, ABS_Y, tw->data[1]); 70 input_report_key(dev, BTN_TOUCH, 1); 71 input_sync(dev); 72 tw->idx = 0; 73 } 74 } else if (tw->touched) { /* untouch */ 75 input_report_key(dev, BTN_TOUCH, 0); 76 input_sync(dev); 77 tw->idx = 0; 78 tw->touched = 0; 79 } 80 81 return IRQ_HANDLED; 82 } 83 84 /* 85 * tw_disconnect() is the opposite of tw_connect() 86 */ 87 88 static void tw_disconnect(struct serio *serio) 89 { 90 struct tw *tw = serio_get_drvdata(serio); 91 92 input_get_device(tw->dev); 93 input_unregister_device(tw->dev); 94 serio_close(serio); 95 serio_set_drvdata(serio, NULL); 96 input_put_device(tw->dev); 97 kfree(tw); 98 } 99 100 /* 101 * tw_connect() is the routine that is called when someone adds a 102 * new serio device that supports the Touchwin protocol and registers it as 103 * an input device. 104 */ 105 106 static int tw_connect(struct serio *serio, struct serio_driver *drv) 107 { 108 struct tw *tw; 109 struct input_dev *input_dev; 110 int err; 111 112 tw = kzalloc(sizeof(*tw), GFP_KERNEL); 113 input_dev = input_allocate_device(); 114 if (!tw || !input_dev) { 115 err = -ENOMEM; 116 goto fail1; 117 } 118 119 tw->serio = serio; 120 tw->dev = input_dev; 121 snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys); 122 123 input_dev->name = "Touchwindow Serial TouchScreen"; 124 input_dev->phys = tw->phys; 125 input_dev->id.bustype = BUS_RS232; 126 input_dev->id.vendor = SERIO_TOUCHWIN; 127 input_dev->id.product = 0; 128 input_dev->id.version = 0x0100; 129 input_dev->dev.parent = &serio->dev; 130 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 131 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 132 input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0); 133 input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0); 134 135 serio_set_drvdata(serio, tw); 136 137 err = serio_open(serio, drv); 138 if (err) 139 goto fail2; 140 141 err = input_register_device(tw->dev); 142 if (err) 143 goto fail3; 144 145 return 0; 146 147 fail3: serio_close(serio); 148 fail2: serio_set_drvdata(serio, NULL); 149 fail1: input_free_device(input_dev); 150 kfree(tw); 151 return err; 152 } 153 154 /* 155 * The serio driver structure. 156 */ 157 158 static const struct serio_device_id tw_serio_ids[] = { 159 { 160 .type = SERIO_RS232, 161 .proto = SERIO_TOUCHWIN, 162 .id = SERIO_ANY, 163 .extra = SERIO_ANY, 164 }, 165 { 0 } 166 }; 167 168 MODULE_DEVICE_TABLE(serio, tw_serio_ids); 169 170 static struct serio_driver tw_drv = { 171 .driver = { 172 .name = "touchwin", 173 }, 174 .description = DRIVER_DESC, 175 .id_table = tw_serio_ids, 176 .interrupt = tw_interrupt, 177 .connect = tw_connect, 178 .disconnect = tw_disconnect, 179 }; 180 181 module_serio_driver(tw_drv); 182