]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/input/touchscreen/elo.c
Input: elo - fix checksum calculation
[linux-2.6-omap-h63xx.git] / drivers / input / touchscreen / elo.c
1 /*
2  * Elo serial touchscreen driver
3  *
4  * Copyright (c) 2004 Vojtech Pavlik
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License version 2 as published by
10  * the Free Software Foundation.
11  */
12
13 /*
14  * This driver can handle serial Elo touchscreens using either the Elo standard
15  * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo
16  * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol.
17  */
18
19 #include <linux/errno.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/input.h>
24 #include <linux/serio.h>
25 #include <linux/init.h>
26
27 #define DRIVER_DESC     "Elo serial touchscreen driver"
28
29 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
30 MODULE_DESCRIPTION(DRIVER_DESC);
31 MODULE_LICENSE("GPL");
32
33 /*
34  * Definitions & global arrays.
35  */
36
37 #define ELO_MAX_LENGTH          10
38
39 #define ELO10_LEAD_BYTE         'U'
40
41 #define ELO10_TOUCH_PACKET      'T'
42
43 /*
44  * Per-touchscreen data.
45  */
46
47 struct elo {
48         struct input_dev *dev;
49         struct serio *serio;
50         int id;
51         int idx;
52         unsigned char csum;
53         unsigned char data[ELO_MAX_LENGTH];
54         char phys[32];
55 };
56
57 static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_regs *regs)
58 {
59         struct input_dev *dev = elo->dev;
60
61         elo->data[elo->idx] = data;
62         switch (elo->idx++) {
63                 case 0:
64                         elo->csum = 0xaa;
65                         if (data != ELO10_LEAD_BYTE) {
66                                 pr_debug("elo: unsynchronized data: 0x%02x\n", data);
67                                 elo->idx = 0;
68                         }
69                         break;
70
71                 case 9:
72                         elo->idx = 0;
73                         if (data != elo->csum) {
74                                 pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n",
75                                          data, elo->csum);
76                                 break;
77                         }
78                         if (elo->data[1] != ELO10_TOUCH_PACKET) {
79                                 pr_debug(elo: "unexpected packet: 0x%02x\n", elo->data[1]);
80                                 break;
81                         }
82                         input_regs(dev, regs);
83                         input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
84                         input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
85                         input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
86                         input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]);
87                         input_sync(dev);
88                         break;
89         }
90         elo->csum += data;
91 }
92
93 static void elo_process_data_6(struct elo *elo, unsigned char data, struct pt_regs *regs)
94 {
95         struct input_dev *dev = elo->dev;
96
97         elo->data[elo->idx] = data;
98
99         switch (elo->idx++) {
100
101                 case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break;
102                 case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break;
103                 case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break;
104
105                 case 3:
106                         if (data & 0xc0) {
107                                 elo->idx = 0;
108                                 break;
109                         }
110
111                         input_regs(dev, regs);
112                         input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
113                         input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
114
115                         if (elo->id == 2) {
116                                 input_report_key(dev, BTN_TOUCH, 1);
117                                 input_sync(dev);
118                                 elo->idx = 0;
119                         }
120
121                         break;
122
123                 case 4:
124                         if (data) {
125                                 input_sync(dev);
126                                 elo->idx = 0;
127                         }
128                         break;
129
130                 case 5:
131                         if ((data & 0xf0) == 0) {
132                                 input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
133                                 input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
134                         }
135                         input_sync(dev);
136                         elo->idx = 0;
137                         break;
138         }
139 }
140
141 static void elo_process_data_3(struct elo *elo, unsigned char data, struct pt_regs *regs)
142 {
143         struct input_dev *dev = elo->dev;
144
145         elo->data[elo->idx] = data;
146
147         switch (elo->idx++) {
148
149                 case 0:
150                         if ((data & 0x7f) != 0x01)
151                                 elo->idx = 0;
152                         break;
153                 case 2:
154                         input_regs(dev, regs);
155                         input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
156                         input_report_abs(dev, ABS_X, elo->data[1]);
157                         input_report_abs(dev, ABS_Y, elo->data[2]);
158                         input_sync(dev);
159                         elo->idx = 0;
160                         break;
161         }
162 }
163
164 static irqreturn_t elo_interrupt(struct serio *serio,
165                 unsigned char data, unsigned int flags, struct pt_regs *regs)
166 {
167         struct elo *elo = serio_get_drvdata(serio);
168
169         switch(elo->id) {
170                 case 0:
171                         elo_process_data_10(elo, data, regs);
172                         break;
173
174                 case 1:
175                 case 2:
176                         elo_process_data_6(elo, data, regs);
177                         break;
178
179                 case 3:
180                         elo_process_data_3(elo, data, regs);
181                         break;
182         }
183
184         return IRQ_HANDLED;
185 }
186
187 /*
188  * elo_disconnect() is the opposite of elo_connect()
189  */
190
191 static void elo_disconnect(struct serio *serio)
192 {
193         struct elo *elo = serio_get_drvdata(serio);
194
195         input_get_device(elo->dev);
196         input_unregister_device(elo->dev);
197         serio_close(serio);
198         serio_set_drvdata(serio, NULL);
199         input_put_device(elo->dev);
200         kfree(elo);
201 }
202
203 /*
204  * elo_connect() is the routine that is called when someone adds a
205  * new serio device that supports Gunze protocol and registers it as
206  * an input device.
207  */
208
209 static int elo_connect(struct serio *serio, struct serio_driver *drv)
210 {
211         struct elo *elo;
212         struct input_dev *input_dev;
213         int err;
214
215         elo = kzalloc(sizeof(struct elo), GFP_KERNEL);
216         input_dev = input_allocate_device();
217         if (!elo || !input_dev) {
218                 err = -ENOMEM;
219                 goto fail1;
220         }
221
222         elo->serio = serio;
223         elo->id = serio->id.id;
224         elo->dev = input_dev;
225         snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
226
227         input_dev->private = elo;
228         input_dev->name = "Elo Serial TouchScreen";
229         input_dev->phys = elo->phys;
230         input_dev->id.bustype = BUS_RS232;
231         input_dev->id.vendor = SERIO_ELO;
232         input_dev->id.product = elo->id;
233         input_dev->id.version = 0x0100;
234         input_dev->cdev.dev = &serio->dev;
235
236         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
237         input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
238
239         switch (elo->id) {
240
241                 case 0: /* 10-byte protocol */
242                         input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
243                         input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
244                         input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
245                         break;
246
247                 case 1: /* 6-byte protocol */
248                         input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
249
250                 case 2: /* 4-byte protocol */
251                         input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
252                         input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
253                         break;
254
255                 case 3: /* 3-byte protocol */
256                         input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
257                         input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
258                         break;
259         }
260
261         serio_set_drvdata(serio, elo);
262
263         err = serio_open(serio, drv);
264         if (err)
265                 goto fail2;
266
267         err = input_register_device(elo->dev);
268         if (err)
269                 goto fail3;
270
271         return 0;
272
273  fail3: serio_close(serio);
274  fail2: serio_set_drvdata(serio, NULL);
275  fail1: input_free_device(input_dev);
276         kfree(elo);
277         return err;
278 }
279
280 /*
281  * The serio driver structure.
282  */
283
284 static struct serio_device_id elo_serio_ids[] = {
285         {
286                 .type   = SERIO_RS232,
287                 .proto  = SERIO_ELO,
288                 .id     = SERIO_ANY,
289                 .extra  = SERIO_ANY,
290         },
291         { 0 }
292 };
293
294 MODULE_DEVICE_TABLE(serio, elo_serio_ids);
295
296 static struct serio_driver elo_drv = {
297         .driver         = {
298                 .name   = "elo",
299         },
300         .description    = DRIVER_DESC,
301         .id_table       = elo_serio_ids,
302         .interrupt      = elo_interrupt,
303         .connect        = elo_connect,
304         .disconnect     = elo_disconnect,
305 };
306
307 /*
308  * The functions for inserting/removing us as a module.
309  */
310
311 static int __init elo_init(void)
312 {
313         serio_register_driver(&elo_drv);
314         return 0;
315 }
316
317 static void __exit elo_exit(void)
318 {
319         serio_unregister_driver(&elo_drv);
320 }
321
322 module_init(elo_init);
323 module_exit(elo_exit);