aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/wacom_w8001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/wacom_w8001.c')
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c71
1 files changed, 40 insertions, 31 deletions
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 9ae4c7b16ba7..8ed53aded2d3 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -15,10 +15,11 @@
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/input.h> 18#include <linux/input/mt.h>
19#include <linux/serio.h> 19#include <linux/serio.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/ctype.h> 21#include <linux/ctype.h>
22#include <linux/delay.h>
22 23
23#define DRIVER_DESC "Wacom W8001 serial touchscreen driver" 24#define DRIVER_DESC "Wacom W8001 serial touchscreen driver"
24 25
@@ -37,6 +38,7 @@ MODULE_LICENSE("GPL");
37 38
38#define W8001_QUERY_PACKET 0x20 39#define W8001_QUERY_PACKET 0x20
39 40
41#define W8001_CMD_STOP '0'
40#define W8001_CMD_START '1' 42#define W8001_CMD_START '1'
41#define W8001_CMD_QUERY '*' 43#define W8001_CMD_QUERY '*'
42#define W8001_CMD_TOUCHQUERY '%' 44#define W8001_CMD_TOUCHQUERY '%'
@@ -48,8 +50,6 @@ MODULE_LICENSE("GPL");
48#define W8001_PKTLEN_TPCCTL 11 /* control packet */ 50#define W8001_PKTLEN_TPCCTL 11 /* control packet */
49#define W8001_PKTLEN_TOUCH2FG 13 51#define W8001_PKTLEN_TOUCH2FG 13
50 52
51#define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */
52
53struct w8001_coord { 53struct w8001_coord {
54 u8 rdy; 54 u8 rdy;
55 u8 tsw; 55 u8 tsw;
@@ -87,7 +87,6 @@ struct w8001 {
87 char phys[32]; 87 char phys[32];
88 int type; 88 int type;
89 unsigned int pktlen; 89 unsigned int pktlen;
90 int trkid[2];
91}; 90};
92 91
93static void parse_data(u8 *data, struct w8001_coord *coord) 92static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -116,28 +115,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
116 115
117static void parse_touch(struct w8001 *w8001) 116static void parse_touch(struct w8001 *w8001)
118{ 117{
119 static int trkid;
120 struct input_dev *dev = w8001->dev; 118 struct input_dev *dev = w8001->dev;
121 unsigned char *data = w8001->data; 119 unsigned char *data = w8001->data;
122 int i; 120 int i;
123 121
124 for (i = 0; i < 2; i++) { 122 for (i = 0; i < 2; i++) {
125 input_mt_slot(dev, i); 123 bool touch = data[0] & (1 << i);
126 124
127 if (data[0] & (1 << i)) { 125 input_mt_slot(dev, i);
126 input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch);
127 if (touch) {
128 int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); 128 int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
129 int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); 129 int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
130 /* data[5,6] and [11,12] is finger capacity */ 130 /* data[5,6] and [11,12] is finger capacity */
131 131
132 input_report_abs(dev, ABS_MT_POSITION_X, x); 132 input_report_abs(dev, ABS_MT_POSITION_X, x);
133 input_report_abs(dev, ABS_MT_POSITION_Y, y); 133 input_report_abs(dev, ABS_MT_POSITION_Y, y);
134 input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
135 if (w8001->trkid[i] < 0)
136 w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
137 } else {
138 w8001->trkid[i] = -1;
139 } 134 }
140 input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
141 } 135 }
142 136
143 input_sync(dev); 137 input_sync(dev);
@@ -287,24 +281,46 @@ static int w8001_setup(struct w8001 *w8001)
287 struct w8001_coord coord; 281 struct w8001_coord coord;
288 int error; 282 int error;
289 283
290 error = w8001_command(w8001, W8001_CMD_QUERY, true); 284 error = w8001_command(w8001, W8001_CMD_STOP, false);
291 if (error) 285 if (error)
292 return error; 286 return error;
293 287
294 parse_data(w8001->response, &coord); 288 msleep(250); /* wait 250ms before querying the device */
295 289
296 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); 290 /* penabled? */
297 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); 291 error = w8001_command(w8001, W8001_CMD_QUERY, true);
298 input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); 292 if (!error) {
299 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); 293 __set_bit(BTN_TOOL_PEN, dev->keybit);
300 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); 294 __set_bit(BTN_TOOL_RUBBER, dev->keybit);
295 __set_bit(BTN_STYLUS, dev->keybit);
296 __set_bit(BTN_STYLUS2, dev->keybit);
297 parse_data(w8001->response, &coord);
298
299 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
300 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
301 input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
302 if (coord.tilt_x && coord.tilt_y) {
303 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
304 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
305 }
306 }
301 307
308 /* Touch enabled? */
302 error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true); 309 error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
303 if (!error) { 310
311 /*
312 * Some non-touch devices may reply to the touch query. But their
313 * second byte is empty, which indicates touch is not supported.
314 */
315 if (!error && w8001->response[1]) {
304 struct w8001_touch_query touch; 316 struct w8001_touch_query touch;
305 317
306 parse_touchquery(w8001->response, &touch); 318 parse_touchquery(w8001->response, &touch);
307 319
320 input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
321 input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
322 __set_bit(BTN_TOOL_FINGER, dev->keybit);
323
308 switch (touch.sensor_id) { 324 switch (touch.sensor_id) {
309 case 0: 325 case 0:
310 case 2: 326 case 2:
@@ -318,15 +334,13 @@ static int w8001_setup(struct w8001 *w8001)
318 case 5: 334 case 5:
319 w8001->pktlen = W8001_PKTLEN_TOUCH2FG; 335 w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
320 336
321 input_mt_create_slots(dev, 2); 337 input_mt_init_slots(dev, 2);
322 input_set_abs_params(dev, ABS_MT_TRACKING_ID,
323 0, MAX_TRACKING_ID, 0, 0);
324 input_set_abs_params(dev, ABS_MT_POSITION_X, 338 input_set_abs_params(dev, ABS_MT_POSITION_X,
325 0, touch.x, 0, 0); 339 0, touch.x, 0, 0);
326 input_set_abs_params(dev, ABS_MT_POSITION_Y, 340 input_set_abs_params(dev, ABS_MT_POSITION_Y,
327 0, touch.y, 0, 0); 341 0, touch.y, 0, 0);
328 input_set_abs_params(dev, ABS_MT_TOOL_TYPE, 342 input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
329 0, 0, 0, 0); 343 0, MT_TOOL_MAX, 0, 0);
330 break; 344 break;
331 } 345 }
332 } 346 }
@@ -372,7 +386,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
372 w8001->serio = serio; 386 w8001->serio = serio;
373 w8001->id = serio->id.id; 387 w8001->id = serio->id.id;
374 w8001->dev = input_dev; 388 w8001->dev = input_dev;
375 w8001->trkid[0] = w8001->trkid[1] = -1;
376 init_completion(&w8001->cmd_done); 389 init_completion(&w8001->cmd_done);
377 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); 390 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
378 391
@@ -385,11 +398,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
385 input_dev->dev.parent = &serio->dev; 398 input_dev->dev.parent = &serio->dev;
386 399
387 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 400 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
388 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 401 __set_bit(BTN_TOUCH, input_dev->keybit);
389 input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
390 input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
391 input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
392 input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
393 402
394 serio_set_drvdata(serio, w8001); 403 serio_set_drvdata(serio, w8001);
395 err = serio_open(serio, drv); 404 err = serio_open(serio, drv);