aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Sung <penmount.touch@gmail.com>2011-09-09 16:33:12 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-09-21 01:46:29 -0400
commit90aba7d8b155c2c39e269608e4a446190e3cd704 (patch)
tree21883b5438253be3330645468b3507454e5f9ed2
parentc42e2e406ad49f320947ba044d3bbf9b05703089 (diff)
Input: penmount - add PenMount 3000 support
Add dual touch support for PenMount 3000 touch controller. Signed-off-by: John Sung <penmount.touch@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/input/touchscreen/penmount.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index e9117adcf6df..71422b91dc46 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -19,6 +19,7 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/input/mt.h>
22#include <linux/serio.h> 23#include <linux/serio.h>
23#include <linux/init.h> 24#include <linux/init.h>
24 25
@@ -34,6 +35,17 @@ MODULE_LICENSE("GPL");
34 */ 35 */
35 36
36#define PM_MAX_LENGTH 6 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
45struct mt_slot {
46 unsigned short x, y;
47 bool active; /* is the touch valid? */
48};
37 49
38/* 50/*
39 * Per-touchscreen data. 51 * Per-touchscreen data.
@@ -46,9 +58,33 @@ struct pm {
46 unsigned char data[PM_MAX_LENGTH]; 58 unsigned char data[PM_MAX_LENGTH];
47 char phys[32]; 59 char phys[32];
48 unsigned char packetsize; 60 unsigned char packetsize;
61 unsigned char maxcontacts;
62 struct mt_slot slots[PM_MAX_MTSLOT];
49}; 63};
50 64
51/* 65/*
66 * pm_mtevent() sends mt events and also emulates pointer movement
67 */
68
69static 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/*
52 * pm_checkpacket() checks if data packet is valid 88 * pm_checkpacket() checks if data packet is valid
53 */ 89 */
54 90
@@ -99,6 +135,21 @@ static irqreturn_t pm_interrupt(struct serio *serio,
99 } 135 }
100 } 136 }
101 break; 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;
102 } 153 }
103 154
104 return IRQ_HANDLED; 155 return IRQ_HANDLED;
@@ -130,6 +181,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
130{ 181{
131 struct pm *pm; 182 struct pm *pm;
132 struct input_dev *input_dev; 183 struct input_dev *input_dev;
184 int max_x, max_y;
133 int err; 185 int err;
134 186
135 pm = kzalloc(sizeof(struct pm), GFP_KERNEL); 187 pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
@@ -142,6 +194,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
142 pm->serio = serio; 194 pm->serio = serio;
143 pm->dev = input_dev; 195 pm->dev = input_dev;
144 snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); 196 snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
197 pm->maxcontacts = 1;
145 198
146 input_dev->name = "PenMount Serial TouchScreen"; 199 input_dev->name = "PenMount Serial TouchScreen";
147 input_dev->phys = pm->phys; 200 input_dev->phys = pm->phys;
@@ -151,24 +204,42 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
151 input_dev->id.version = 0x0100; 204 input_dev->id.version = 0x0100;
152 input_dev->dev.parent = &serio->dev; 205 input_dev->dev.parent = &serio->dev;
153 206
154 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 207 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
155 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 208 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
156 input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
157 input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
158 209
159 switch (serio->id.id) { 210 switch (serio->id.id) {
160 default: 211 default:
161 case 0: 212 case 0:
162 pm->packetsize = 5; 213 pm->packetsize = 5;
163 input_dev->id.product = 0x9000; 214 input_dev->id.product = 0x9000;
215 max_x = max_y = 0x3ff;
164 break; 216 break;
165 217
166 case 1: 218 case 1:
167 pm->packetsize = 6; 219 pm->packetsize = 6;
168 input_dev->id.product = 0x6000; 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;
169 break; 229 break;
170 } 230 }
171 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
172 serio_set_drvdata(serio, pm); 243 serio_set_drvdata(serio, pm);
173 244
174 err = serio_open(serio, drv); 245 err = serio_open(serio, drv);