]> Pileus Git - ~andy/linux/blob - drivers/input/touchscreen/penmount.c
Input: penmount - add PenMount 3000 support
[~andy/linux] / drivers / input / touchscreen / penmount.c
1 /*
2  * Penmount serial touchscreen driver
3  *
4  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
5  * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
6  *
7  * Based on ELO driver (drivers/input/touchscreen/elo.c)
8  * Copyright (c) 2004 Vojtech Pavlik
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/input/mt.h>
23 #include <linux/serio.h>
24 #include <linux/init.h>
25
26 #define DRIVER_DESC     "PenMount serial touchscreen driver"
27
28 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
29 MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>");
30 MODULE_DESCRIPTION(DRIVER_DESC);
31 MODULE_LICENSE("GPL");
32
33 /*
34  * Definitions & global arrays.
35  */
36
37 #define PM_MAX_LENGTH   6
38 #define PM_MAX_MTSLOT   16
39 #define PM_3000_MTSLOT  2
40
41 /*
42  * Multi-touch slot
43  */
44
45 struct mt_slot {
46         unsigned short x, y;
47         bool active; /* is the touch valid? */
48 };
49
50 /*
51  * Per-touchscreen data.
52  */
53
54 struct pm {
55         struct input_dev *dev;
56         struct serio *serio;
57         int idx;
58         unsigned char data[PM_MAX_LENGTH];
59         char phys[32];
60         unsigned char packetsize;
61         unsigned char maxcontacts;
62         struct mt_slot slots[PM_MAX_MTSLOT];
63 };
64
65 /*
66  * pm_mtevent() sends mt events and also emulates pointer movement
67  */
68
69 static void pm_mtevent(struct pm *pm, struct input_dev *input)
70 {
71         int i;
72
73         for (i = 0; i < pm->maxcontacts; ++i) {
74                 input_mt_slot(input, i);
75                 input_mt_report_slot_state(input, MT_TOOL_FINGER,
76                                 pm->slots[i].active);
77                 if (pm->slots[i].active) {
78                         input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x);
79                         input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y);
80                 }
81         }
82
83         input_mt_report_pointer_emulation(input, true);
84         input_sync(input);
85 }
86
87 /*
88  * pm_checkpacket() checks if data packet is valid
89  */
90
91 static bool pm_checkpacket(unsigned char *packet)
92 {
93         int total = 0;
94         int i;
95
96         for (i = 0; i < 5; i++)
97                 total += packet[i];
98
99         return packet[5] == (unsigned char)~(total & 0xff);
100 }
101
102 static irqreturn_t pm_interrupt(struct serio *serio,
103                 unsigned char data, unsigned int flags)
104 {
105         struct pm *pm = serio_get_drvdata(serio);
106         struct input_dev *dev = pm->dev;
107
108         pm->data[pm->idx] = data;
109
110         switch (pm->dev->id.product) {
111         case 0x9000:
112                 if (pm->data[0] & 0x80) {
113                         if (pm->packetsize == ++pm->idx) {
114                                 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
115                                 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
116                                 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
117                                 input_sync(dev);
118                                 pm->idx = 0;
119                         }
120                 }
121                 break;
122
123         case 0x6000:
124                 if ((pm->data[0] & 0xbf) == 0x30) {
125                         if (pm->packetsize == ++pm->idx) {
126                                 if (pm_checkpacket(pm->data)) {
127                                         input_report_abs(dev, ABS_X,
128                                                         pm->data[2] * 256 + pm->data[1]);
129                                         input_report_abs(dev, ABS_Y,
130                                                         pm->data[4] * 256 + pm->data[3]);
131                                         input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
132                                         input_sync(dev);
133                                 }
134                                 pm->idx = 0;
135                         }
136                 }
137                 break;
138
139         case 0x3000:
140                 if ((pm->data[0] & 0xce) == 0x40) {
141                         if (pm->packetsize == ++pm->idx) {
142                                 if (pm_checkpacket(pm->data)) {
143                                         int slotnum = pm->data[0] & 0x0f;
144                                         pm->slots[slotnum].active = pm->data[0] & 0x30;
145                                         pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
146                                         pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
147                                         pm_mtevent(pm, dev);
148                                 }
149                                 pm->idx = 0;
150                         }
151                 }
152                 break;
153         }
154
155         return IRQ_HANDLED;
156 }
157
158 /*
159  * pm_disconnect() is the opposite of pm_connect()
160  */
161
162 static void pm_disconnect(struct serio *serio)
163 {
164         struct pm *pm = serio_get_drvdata(serio);
165
166         input_get_device(pm->dev);
167         input_unregister_device(pm->dev);
168         serio_close(serio);
169         serio_set_drvdata(serio, NULL);
170         input_put_device(pm->dev);
171         kfree(pm);
172 }
173
174 /*
175  * pm_connect() is the routine that is called when someone adds a
176  * new serio device that supports PenMount protocol and registers it as
177  * an input device.
178  */
179
180 static int pm_connect(struct serio *serio, struct serio_driver *drv)
181 {
182         struct pm *pm;
183         struct input_dev *input_dev;
184         int max_x, max_y;
185         int err;
186
187         pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
188         input_dev = input_allocate_device();
189         if (!pm || !input_dev) {
190                 err = -ENOMEM;
191                 goto fail1;
192         }
193
194         pm->serio = serio;
195         pm->dev = input_dev;
196         snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
197         pm->maxcontacts = 1;
198
199         input_dev->name = "PenMount Serial TouchScreen";
200         input_dev->phys = pm->phys;
201         input_dev->id.bustype = BUS_RS232;
202         input_dev->id.vendor = SERIO_PENMOUNT;
203         input_dev->id.product = 0;
204         input_dev->id.version = 0x0100;
205         input_dev->dev.parent = &serio->dev;
206
207         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
208         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
209
210         switch (serio->id.id) {
211         default:
212         case 0:
213                 pm->packetsize = 5;
214                 input_dev->id.product = 0x9000;
215                 max_x = max_y = 0x3ff;
216                 break;
217
218         case 1:
219                 pm->packetsize = 6;
220                 input_dev->id.product = 0x6000;
221                 max_x = max_y = 0x3ff;
222                 break;
223
224         case 2:
225                 pm->packetsize = 6;
226                 input_dev->id.product = 0x3000;
227                 max_x = max_y = 0x7ff;
228                 pm->maxcontacts = PM_3000_MTSLOT;
229                 break;
230         }
231
232         input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
233         input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
234
235         if (pm->maxcontacts > 1) {
236                 input_mt_init_slots(pm->dev, pm->maxcontacts);
237                 input_set_abs_params(pm->dev,
238                                      ABS_MT_POSITION_X, 0, max_x, 0, 0);
239                 input_set_abs_params(pm->dev,
240                                      ABS_MT_POSITION_Y, 0, max_y, 0, 0);
241         }
242
243         serio_set_drvdata(serio, pm);
244
245         err = serio_open(serio, drv);
246         if (err)
247                 goto fail2;
248
249         err = input_register_device(pm->dev);
250         if (err)
251                 goto fail3;
252
253         return 0;
254
255  fail3: serio_close(serio);
256  fail2: serio_set_drvdata(serio, NULL);
257  fail1: input_free_device(input_dev);
258         kfree(pm);
259         return err;
260 }
261
262 /*
263  * The serio driver structure.
264  */
265
266 static struct serio_device_id pm_serio_ids[] = {
267         {
268                 .type   = SERIO_RS232,
269                 .proto  = SERIO_PENMOUNT,
270                 .id     = SERIO_ANY,
271                 .extra  = SERIO_ANY,
272         },
273         { 0 }
274 };
275
276 MODULE_DEVICE_TABLE(serio, pm_serio_ids);
277
278 static struct serio_driver pm_drv = {
279         .driver         = {
280                 .name   = "serio-penmount",
281         },
282         .description    = DRIVER_DESC,
283         .id_table       = pm_serio_ids,
284         .interrupt      = pm_interrupt,
285         .connect        = pm_connect,
286         .disconnect     = pm_disconnect,
287 };
288
289 /*
290  * The functions for inserting/removing us as a module.
291  */
292
293 static int __init pm_init(void)
294 {
295         return serio_register_driver(&pm_drv);
296 }
297
298 static void __exit pm_exit(void)
299 {
300         serio_unregister_driver(&pm_drv);
301 }
302
303 module_init(pm_init);
304 module_exit(pm_exit);