diff options
Diffstat (limited to 'drivers/input/touchscreen/wacom_w8001.c')
-rw-r--r-- | drivers/input/touchscreen/wacom_w8001.c | 71 |
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 | |||
53 | struct w8001_coord { | 53 | struct 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 | ||
93 | static void parse_data(u8 *data, struct w8001_coord *coord) | 92 | static 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 | ||
117 | static void parse_touch(struct w8001 *w8001) | 116 | static 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); |