1 /* 2 * Touchright serial touchscreen driver 3 * 4 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> 5 * 6 * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c) 7 * Copyright (c) 2004 Vojtech Pavlik 8 * and Dan Streetman <ddstreet@ieee.org> 9 */ 10 11 /* 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License version 2 as published 14 * by the Free Software Foundation. 15 */ 16 17 #include <linux/errno.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <linux/slab.h> 21 #include <linux/input.h> 22 #include <linux/serio.h> 23 24 #define DRIVER_DESC "Touchright serial touchscreen driver" 25 26 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); 27 MODULE_DESCRIPTION(DRIVER_DESC); 28 MODULE_LICENSE("GPL"); 29 30 /* 31 * Definitions & global arrays. 32 */ 33 34 #define TR_FORMAT_TOUCH_BIT 0x01 35 #define TR_FORMAT_STATUS_BYTE 0x40 36 #define TR_FORMAT_STATUS_MASK ~TR_FORMAT_TOUCH_BIT 37 38 #define TR_LENGTH 5 39 40 #define TR_MIN_XC 0 41 #define TR_MAX_XC 0x1ff 42 #define TR_MIN_YC 0 43 #define TR_MAX_YC 0x1ff 44 45 /* 46 * Per-touchscreen data. 47 */ 48 49 struct tr { 50 struct input_dev *dev; 51 struct serio *serio; 52 int idx; 53 unsigned char data[TR_LENGTH]; 54 char phys[32]; 55 }; 56 57 static irqreturn_t tr_interrupt(struct serio *serio, 58 unsigned char data, unsigned int flags) 59 { 60 struct tr *tr = serio_get_drvdata(serio); 61 struct input_dev *dev = tr->dev; 62 63 tr->data[tr->idx] = data; 64 65 if ((tr->data[0] & TR_FORMAT_STATUS_MASK) == TR_FORMAT_STATUS_BYTE) { 66 if (++tr->idx == TR_LENGTH) { 67 input_report_abs(dev, ABS_X, 68 (tr->data[1] << 5) | (tr->data[2] >> 1)); 69 input_report_abs(dev, ABS_Y, 70 (tr->data[3] << 5) | (tr->data[4] >> 1)); 71 input_report_key(dev, BTN_TOUCH, 72 tr->data[0] & TR_FORMAT_TOUCH_BIT); 73 input_sync(dev); 74 tr->idx = 0; 75 } 76 } 77 78 return IRQ_HANDLED; 79 } 80 81 /* 82 * tr_disconnect() is the opposite of tr_connect() 83 */ 84 85 static void tr_disconnect(struct serio *serio) 86 { 87 struct tr *tr = serio_get_drvdata(serio); 88 89 input_get_device(tr->dev); 90 input_unregister_device(tr->dev); 91 serio_close(serio); 92 serio_set_drvdata(serio, NULL); 93 input_put_device(tr->dev); 94 kfree(tr); 95 } 96 97 /* 98 * tr_connect() is the routine that is called when someone adds a 99 * new serio device that supports the Touchright protocol and registers it as 100 * an input device. 101 */ 102 103 static int tr_connect(struct serio *serio, struct serio_driver *drv) 104 { 105 struct tr *tr; 106 struct input_dev *input_dev; 107 int err; 108 109 tr = kzalloc(sizeof(struct tr), GFP_KERNEL); 110 input_dev = input_allocate_device(); 111 if (!tr || !input_dev) { 112 err = -ENOMEM; 113 goto fail1; 114 } 115 116 tr->serio = serio; 117 tr->dev = input_dev; 118 snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys); 119 120 input_dev->name = "Touchright Serial TouchScreen"; 121 input_dev->phys = tr->phys; 122 input_dev->id.bustype = BUS_RS232; 123 input_dev->id.vendor = SERIO_TOUCHRIGHT; 124 input_dev->id.product = 0; 125 input_dev->id.version = 0x0100; 126 input_dev->dev.parent = &serio->dev; 127 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 128 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 129 input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0); 130 input_set_abs_params(tr->dev, ABS_Y, TR_MIN_YC, TR_MAX_YC, 0, 0); 131 132 serio_set_drvdata(serio, tr); 133 134 err = serio_open(serio, drv); 135 if (err) 136 goto fail2; 137 138 err = input_register_device(tr->dev); 139 if (err) 140 goto fail3; 141 142 return 0; 143 144 fail3: serio_close(serio); 145 fail2: serio_set_drvdata(serio, NULL); 146 fail1: input_free_device(input_dev); 147 kfree(tr); 148 return err; 149 } 150 151 /* 152 * The serio driver structure. 153 */ 154 155 static struct serio_device_id tr_serio_ids[] = { 156 { 157 .type = SERIO_RS232, 158 .proto = SERIO_TOUCHRIGHT, 159 .id = SERIO_ANY, 160 .extra = SERIO_ANY, 161 }, 162 { 0 } 163 }; 164 165 MODULE_DEVICE_TABLE(serio, tr_serio_ids); 166 167 static struct serio_driver tr_drv = { 168 .driver = { 169 .name = "touchright", 170 }, 171 .description = DRIVER_DESC, 172 .id_table = tr_serio_ids, 173 .interrupt = tr_interrupt, 174 .connect = tr_connect, 175 .disconnect = tr_disconnect, 176 }; 177 178 module_serio_driver(tr_drv); 179