aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2010-08-29 01:00:47 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-29 01:46:10 -0400
commitaaba933eeb8d7f804508bc74baa58656240107f8 (patch)
treec2d5d1e94601f04fe74bdd44131d619c4cbcf4ef /drivers/input/touchscreen
parent2072f8db625cbdaba839fe7bb1b607d06884e685 (diff)
Input: wacom_w8001 - support (and ignore) touch tablets
Tablets that support touch input may report different sized packages, depending on the touch sensor in the tablet. For now, discard the packages until we report them as touch input proper. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c88
1 files changed, 86 insertions, 2 deletions
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index bc642f1be376..89abda06db74 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -2,6 +2,7 @@
2 * Wacom W8001 penabled serial touchscreen driver 2 * Wacom W8001 penabled serial touchscreen driver
3 * 3 *
4 * Copyright (c) 2008 Jaya Kumar 4 * Copyright (c) 2008 Jaya Kumar
5 * Copyright (c) 2010 Red Hat, Inc.
5 * 6 *
6 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for 8 * License. See the file COPYING in the main directory of this archive for
@@ -30,11 +31,22 @@ MODULE_LICENSE("GPL");
30#define W8001_LEAD_BYTE 0x80 31#define W8001_LEAD_BYTE 0x80
31#define W8001_TAB_MASK 0x40 32#define W8001_TAB_MASK 0x40
32#define W8001_TAB_BYTE 0x40 33#define W8001_TAB_BYTE 0x40
34/* set in first byte of touch data packets */
35#define W8001_TOUCH_MASK (0x10 | W8001_LEAD_MASK)
36#define W8001_TOUCH_BYTE (0x10 | W8001_LEAD_BYTE)
33 37
34#define W8001_QUERY_PACKET 0x20 38#define W8001_QUERY_PACKET 0x20
35 39
36#define W8001_CMD_START '1' 40#define W8001_CMD_START '1'
37#define W8001_CMD_QUERY '*' 41#define W8001_CMD_QUERY '*'
42#define W8001_CMD_TOUCHQUERY '%'
43
44/* length of data packets in bytes, depends on device. */
45#define W8001_PKTLEN_TOUCH93 5
46#define W8001_PKTLEN_TOUCH9A 7
47#define W8001_PKTLEN_TPCPEN 9
48#define W8001_PKTLEN_TPCCTL 11 /* control packet */
49#define W8001_PKTLEN_TOUCH2FG 13
38 50
39struct w8001_coord { 51struct w8001_coord {
40 u8 rdy; 52 u8 rdy;
@@ -48,6 +60,15 @@ struct w8001_coord {
48 u8 tilt_y; 60 u8 tilt_y;
49}; 61};
50 62
63/* touch query reply packet */
64struct w8001_touch_query {
65 u8 panel_res;
66 u8 capacity_res;
67 u8 sensor_id;
68 u16 x;
69 u16 y;
70};
71
51/* 72/*
52 * Per-touchscreen data. 73 * Per-touchscreen data.
53 */ 74 */
@@ -63,6 +84,7 @@ struct w8001 {
63 unsigned char data[W8001_MAX_LENGTH]; 84 unsigned char data[W8001_MAX_LENGTH];
64 char phys[32]; 85 char phys[32];
65 int type; 86 int type;
87 unsigned int pktlen;
66}; 88};
67 89
68static void parse_data(u8 *data, struct w8001_coord *coord) 90static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -89,6 +111,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
89 coord->tilt_y = data[8] & 0x7F; 111 coord->tilt_y = data[8] & 0x7F;
90} 112}
91 113
114static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
115{
116 memset(query, 0, sizeof(*query));
117
118 query->panel_res = data[1];
119 query->sensor_id = data[2] & 0x7;
120 query->capacity_res = data[7];
121
122 query->x = data[3] << 9;
123 query->x |= data[4] << 2;
124 query->x |= (data[2] >> 5) & 0x3;
125
126 query->y = data[5] << 9;
127 query->y |= data[6] << 2;
128 query->y |= (data[2] >> 3) & 0x3;
129}
130
92static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) 131static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
93{ 132{
94 struct input_dev *dev = w8001->dev; 133 struct input_dev *dev = w8001->dev;
@@ -147,22 +186,45 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
147 } 186 }
148 break; 187 break;
149 188
150 case 8: 189 case W8001_PKTLEN_TOUCH93 - 1:
190 case W8001_PKTLEN_TOUCH9A - 1:
191 /* ignore one-finger touch packet. */
192 if (w8001->pktlen == w8001->idx)
193 w8001->idx = 0;
194 break;
195
196 /* Pen coordinates packet */
197 case W8001_PKTLEN_TPCPEN - 1:
151 tmp = w8001->data[0] & W8001_TAB_MASK; 198 tmp = w8001->data[0] & W8001_TAB_MASK;
152 if (unlikely(tmp == W8001_TAB_BYTE)) 199 if (unlikely(tmp == W8001_TAB_BYTE))
153 break; 200 break;
154 201
202 tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
203 if (tmp == W8001_TOUCH_BYTE)
204 break;
205
155 w8001->idx = 0; 206 w8001->idx = 0;
156 parse_data(w8001->data, &coord); 207 parse_data(w8001->data, &coord);
157 report_pen_events(w8001, &coord); 208 report_pen_events(w8001, &coord);
158 break; 209 break;
159 210
160 case 10: 211 /* control packet */
212 case W8001_PKTLEN_TPCCTL - 1:
213 tmp = (w8001->data[0] & W8001_TOUCH_MASK);
214 if (tmp == W8001_TOUCH_BYTE)
215 break;
216
161 w8001->idx = 0; 217 w8001->idx = 0;
162 memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH); 218 memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH);
163 w8001->response_type = W8001_QUERY_PACKET; 219 w8001->response_type = W8001_QUERY_PACKET;
164 complete(&w8001->cmd_done); 220 complete(&w8001->cmd_done);
165 break; 221 break;
222
223 case W8001_PKTLEN_TOUCH2FG - 1:
224 /* ignore two-finger touch packet. */
225 if (w8001->pktlen == w8001->idx)
226 w8001->idx = 0;
227 break;
166 } 228 }
167 229
168 return IRQ_HANDLED; 230 return IRQ_HANDLED;
@@ -205,6 +267,28 @@ static int w8001_setup(struct w8001 *w8001)
205 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); 267 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
206 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); 268 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
207 269
270 error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
271 if (!error) {
272 struct w8001_touch_query touch;
273
274 parse_touchquery(w8001->response, &touch);
275
276 switch (touch.sensor_id) {
277 case 0:
278 case 2:
279 w8001->pktlen = W8001_PKTLEN_TOUCH93;
280 break;
281 case 1:
282 case 3:
283 case 4:
284 w8001->pktlen = W8001_PKTLEN_TOUCH9A;
285 break;
286 case 5:
287 w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
288 break;
289 }
290 }
291
208 return w8001_command(w8001, W8001_CMD_START, false); 292 return w8001_command(w8001, W8001_CMD_START, false);
209} 293}
210 294