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 #include <linux/init.h> 24 25 #define DRIVER_DESC "Touchright serial touchscreen driver" 26 27 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); 28 MODULE_DESCRIPTION(DRIVER_DESC); 29 MODULE_LICENSE("GPL"); 30 31 /* 32 * Definitions & global arrays. 33 */ 34 35 #define TR_FORMAT_TOUCH_BIT 0x01 36 #define TR_FORMAT_STATUS_BYTE 0x40 37 #define TR_FORMAT_STATUS_MASK ~TR_FORMAT_TOUCH_BIT 38 39 #define TR_LENGTH 5 40 41 #define TR_MIN_XC 0 42 #define TR_MAX_XC 0x1ff 43 #define TR_MIN_YC 0 44 #define TR_MAX_YC 0x1ff 45 46 /* 47 * Per-touchscreen data. 48 */ 49 50 struct tr { 51 struct input_dev *dev; 52 struct serio *serio; 53 int idx; 54 unsigned char data[TR_LENGTH]; 55 char phys[32]; 56 }; 57 58 static irqreturn_t tr_interrupt(struct serio *serio, 59 unsigned char data, unsigned int flags) 60 { 61 struct tr *tr = serio_get_drvdata(serio); 62 struct input_dev *dev = tr->dev; 63 64 tr->data[tr->idx] = data; 65 66 if ((tr->data[0] & TR_FORMAT_STATUS_MASK) == TR_FORMAT_STATUS_BYTE) { 67 if (++tr->idx == TR_LENGTH) { 68 input_report_abs(dev, ABS_X, 69 (tr->data[1] << 5) | (tr->data[2] >> 1)); 70 input_report_abs(dev, ABS_Y, 71 (tr->data[3] << 5) | (tr->data[4] >> 1)); 72 input_report_key(dev, BTN_TOUCH, 73 tr->data[0] & TR_FORMAT_TOUCH_BIT); 74 input_sync(dev); 75 tr->idx = 0; 76 } 77 } 78 79 return IRQ_HANDLED; 80 } 81 82 /* 83 * tr_disconnect() is the opposite of tr_connect() 84 */ 85 86 static void tr_disconnect(struct serio *serio) 87 { 88 struct tr *tr = serio_get_drvdata(serio); 89 90 input_get_device(tr->dev); 91 input_unregister_device(tr->dev); 92 serio_close(serio); 93 serio_set_drvdata(serio, NULL); 94 input_put_device(tr->dev); 95 kfree(tr); 96 } 97 98 /* 99 * tr_connect() is the routine that is called when someone adds a 100 * new serio device that supports the Touchright protocol and registers it as 101 * an input device. 102 */ 103 104 static int tr_connect(struct serio *serio, struct serio_driver *drv) 105 { 106 struct tr *tr; 107 struct input_dev *input_dev; 108 int err; 109 110 tr = kzalloc(sizeof(struct tr), GFP_KERNEL); 111 input_dev = input_allocate_device(); 112 if (!tr || !input_dev) { 113 err = -ENOMEM; 114 goto fail1; 115 } 116 117 tr->serio = serio; 118 tr->dev = input_dev; 119 snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys); 120 121 input_dev->name = "Touchright Serial TouchScreen"; 122 input_dev->phys = tr->phys; 123 input_dev->id.bustype = BUS_RS232; 124 input_dev->id.vendor = SERIO_TOUCHRIGHT; 125 input_dev->id.product = 0; 126 input_dev->id.version = 0x0100; 127 input_dev->dev.parent = &serio->dev; 128 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 129 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 130 input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0); 131 input_set_abs_params(tr->dev, ABS_Y, TR_MIN_YC, TR_MAX_YC, 0, 0); 132 133 serio_set_drvdata(serio, tr); 134 135 err = serio_open(serio, drv); 136 if (err) 137 goto fail2; 138 139 err = input_register_device(tr->dev); 140 if (err) 141 goto fail3; 142 143 return 0; 144 145 fail3: serio_close(serio); 146 fail2: serio_set_drvdata(serio, NULL); 147 fail1: input_free_device(input_dev); 148 kfree(tr); 149 return err; 150 } 151 152 /* 153 * The serio driver structure. 154 */ 155 156 static struct serio_device_id tr_serio_ids[] = { 157 { 158 .type = SERIO_RS232, 159 .proto = SERIO_TOUCHRIGHT, 160 .id = SERIO_ANY, 161 .extra = SERIO_ANY, 162 }, 163 { 0 } 164 }; 165 166 MODULE_DEVICE_TABLE(serio, tr_serio_ids); 167 168 static struct serio_driver tr_drv = { 169 .driver = { 170 .name = "touchright", 171 }, 172 .description = DRIVER_DESC, 173 .id_table = tr_serio_ids, 174 .interrupt = tr_interrupt, 175 .connect = tr_connect, 176 .disconnect = tr_disconnect, 177 }; 178 179 /* 180 * The functions for inserting/removing us as a module. 181 */ 182 183 static int __init tr_init(void) 184 { 185 return serio_register_driver(&tr_drv); 186 } 187 188 static void __exit tr_exit(void) 189 { 190 serio_unregister_driver(&tr_drv); 191 } 192 193 module_init(tr_init); 194 module_exit(tr_exit); 195