Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us