2 * Penmount serial touchscreen driver
4 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
5 * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
7 * Based on ELO driver (drivers/input/touchscreen/elo.c)
8 * Copyright (c) 2004 Vojtech Pavlik
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.
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>
25 #define DRIVER_DESC "PenMount serial touchscreen driver"
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");
33 * Definitions & global arrays.
36 #define PM_MAX_LENGTH 6
37 #define PM_MAX_MTSLOT 16
38 #define PM_3000_MTSLOT 2
39 #define PM_6250_MTSLOT 12
47 bool active
; /* is the touch valid? */
51 * Per-touchscreen data.
55 struct input_dev
*dev
;
58 unsigned char data
[PM_MAX_LENGTH
];
60 unsigned char packetsize
;
61 unsigned char maxcontacts
;
62 struct mt_slot slots
[PM_MAX_MTSLOT
];
63 void (*parse_packet
)(struct pm
*);
67 * pm_mtevent() sends mt events and also emulates pointer movement
70 static void pm_mtevent(struct pm
*pm
, struct input_dev
*input
)
74 for (i
= 0; i
< pm
->maxcontacts
; ++i
) {
75 input_mt_slot(input
, i
);
76 input_mt_report_slot_state(input
, MT_TOOL_FINGER
,
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
);
84 input_mt_report_pointer_emulation(input
, true);
89 * pm_checkpacket() checks if data packet is valid
92 static bool pm_checkpacket(unsigned char *packet
)
97 for (i
= 0; i
< 5; i
++)
100 return packet
[5] == (unsigned char)~(total
& 0xff);
103 static void pm_parse_9000(struct pm
*pm
)
105 struct input_dev
*dev
= pm
->dev
;
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));
116 static void pm_parse_6000(struct pm
*pm
)
118 struct input_dev
*dev
= pm
->dev
;
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);
133 static void pm_parse_3000(struct pm
*pm
)
135 struct input_dev
*dev
= pm
->dev
;
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];
149 static void pm_parse_6250(struct pm
*pm
)
151 struct input_dev
*dev
= pm
->dev
;
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];
165 static irqreturn_t
pm_interrupt(struct serio
*serio
,
166 unsigned char data
, unsigned int flags
)
168 struct pm
*pm
= serio_get_drvdata(serio
);
170 pm
->data
[pm
->idx
] = data
;
172 pm
->parse_packet(pm
);
178 * pm_disconnect() is the opposite of pm_connect()
181 static void pm_disconnect(struct serio
*serio
)
183 struct pm
*pm
= serio_get_drvdata(serio
);
187 input_unregister_device(pm
->dev
);
190 serio_set_drvdata(serio
, NULL
);
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
199 static int pm_connect(struct serio
*serio
, struct serio_driver
*drv
)
202 struct input_dev
*input_dev
;
206 pm
= kzalloc(sizeof(struct pm
), GFP_KERNEL
);
207 input_dev
= input_allocate_device();
208 if (!pm
|| !input_dev
) {
215 snprintf(pm
->phys
, sizeof(pm
->phys
), "%s/input0", serio
->phys
);
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
;
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
);
229 switch (serio
->id
.id
) {
233 pm
->parse_packet
= pm_parse_9000
;
234 input_dev
->id
.product
= 0x9000;
235 max_x
= max_y
= 0x3ff;
240 pm
->parse_packet
= pm_parse_6000
;
241 input_dev
->id
.product
= 0x6000;
242 max_x
= max_y
= 0x3ff;
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
;
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
;
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);
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);
273 serio_set_drvdata(serio
, pm
);
275 err
= serio_open(serio
, drv
);
279 err
= input_register_device(pm
->dev
);
285 fail3
: serio_close(serio
);
286 fail2
: serio_set_drvdata(serio
, NULL
);
287 fail1
: input_free_device(input_dev
);
293 * The serio driver structure.
296 static struct serio_device_id pm_serio_ids
[] = {
299 .proto
= SERIO_PENMOUNT
,
306 MODULE_DEVICE_TABLE(serio
, pm_serio_ids
);
308 static struct serio_driver pm_drv
= {
310 .name
= "serio-penmount",
312 .description
= DRIVER_DESC
,
313 .id_table
= pm_serio_ids
,
314 .interrupt
= pm_interrupt
,
315 .connect
= pm_connect
,
316 .disconnect
= pm_disconnect
,
319 module_serio_driver(pm_drv
);