aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2010-12-27 20:33:20 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-12-27 20:33:20 -0500
commit5c461b913a16aed8afa285a1d00414791a9afe33 (patch)
tree95c7d32fcb899240e8bc5ab5bfac20d259a81b46
parentef11e701f32fb0cd5c5f0f6fb9a9e28fab151219 (diff)
parent4f56ce929cab45a3a6e1a81700da52bb9bdbfc0f (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt into next
-rw-r--r--Documentation/input/multi-touch-protocol.txt44
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-egalax.c2
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/input/evdev.c4
-rw-r--r--drivers/input/input.c21
-rw-r--r--drivers/input/misc/uinput.c4
-rw-r--r--drivers/input/mouse/synaptics.c95
-rw-r--r--drivers/input/mouse/synaptics.h3
-rw-r--r--include/linux/input.h16
-rw-r--r--include/linux/uinput.h1
11 files changed, 168 insertions, 24 deletions
diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt
index 07215fa0c588..71536e78406f 100644
--- a/Documentation/input/multi-touch-protocol.txt
+++ b/Documentation/input/multi-touch-protocol.txt
@@ -1,6 +1,6 @@
1Multi-touch (MT) Protocol 1Multi-touch (MT) Protocol
2------------------------- 2-------------------------
3 Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se> 3 Copyright (C) 2009-2010 Henrik Rydberg <rydberg@euromail.se>
4 4
5 5
6Introduction 6Introduction
@@ -169,12 +169,16 @@ described by adding the MINOR parameters, such that MAJOR and MINOR are the
169major and minor axis of an ellipse. Finally, the orientation of the oval 169major and minor axis of an ellipse. Finally, the orientation of the oval
170shape can be describe with the ORIENTATION parameter. 170shape can be describe with the ORIENTATION parameter.
171 171
172For type A devices, further specification of the touch shape is possible
173via ABS_MT_BLOB_ID.
174
172The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a 175The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a
173contact or a pen or something else. Devices with more granular information 176finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event
174may specify general shapes as blobs, i.e., as a sequence of rectangular 177may be used to track identified contacts over time [5].
175shapes grouped together by an ABS_MT_BLOB_ID. Finally, for the few devices 178
176that currently support it, the ABS_MT_TRACKING_ID event may be used to 179In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are
177report contact tracking from hardware [5]. 180implicitly handled by input core; drivers should instead call
181input_mt_report_slot_state().
178 182
179 183
180Event Semantics 184Event Semantics
@@ -247,21 +251,24 @@ ABS_MT_TOOL_TYPE
247The type of approaching tool. A lot of kernel drivers cannot distinguish 251The type of approaching tool. A lot of kernel drivers cannot distinguish
248between different tool types, such as a finger or a pen. In such cases, the 252between different tool types, such as a finger or a pen. In such cases, the
249event should be omitted. The protocol currently supports MT_TOOL_FINGER and 253event should be omitted. The protocol currently supports MT_TOOL_FINGER and
250MT_TOOL_PEN [2]. 254MT_TOOL_PEN [2]. For type B devices, this event is handled by input core;
255drivers should instead use input_mt_report_slot_state().
251 256
252ABS_MT_BLOB_ID 257ABS_MT_BLOB_ID
253 258
254The BLOB_ID groups several packets together into one arbitrarily shaped 259The BLOB_ID groups several packets together into one arbitrarily shaped
255contact. This is a low-level anonymous grouping for type A devices, and 260contact. The sequence of points forms a polygon which defines the shape of
261the contact. This is a low-level anonymous grouping for type A devices, and
256should not be confused with the high-level trackingID [5]. Most type A 262should not be confused with the high-level trackingID [5]. Most type A
257devices do not have blob capability, so drivers can safely omit this event. 263devices do not have blob capability, so drivers can safely omit this event.
258 264
259ABS_MT_TRACKING_ID 265ABS_MT_TRACKING_ID
260 266
261The TRACKING_ID identifies an initiated contact throughout its life cycle 267The TRACKING_ID identifies an initiated contact throughout its life cycle
262[5]. This event is mandatory for type B devices. The value range of the 268[5]. The value range of the TRACKING_ID should be large enough to ensure
263TRACKING_ID should be large enough to ensure unique identification of a 269unique identification of a contact maintained over an extended period of
264contact maintained over an extended period of time. 270time. For type B devices, this event is handled by input core; drivers
271should instead use input_mt_report_slot_state().
265 272
266 273
267Event Computation 274Event Computation
@@ -308,18 +315,19 @@ and with ORIENTATION, one can detect twisting of fingers.
308Notes 315Notes
309----- 316-----
310 317
311In order to stay compatible with existing applications, the data 318In order to stay compatible with existing applications, the data reported
312reported in a finger packet must not be recognized as single-touch 319in a finger packet must not be recognized as single-touch events.
313events. In addition, all finger data must bypass input filtering, 320
314since subsequent events of the same type refer to different fingers. 321For type A devices, all finger data bypasses input filtering, since
322subsequent events of the same type refer to different fingers.
315 323
316The first kernel driver to utilize the MT protocol is the bcm5974 driver, 324For example usage of the type A protocol, see the bcm5974 driver. For
317where examples can be found. 325example usage of the type B protocol, see the hid-egalax driver.
318 326
319[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the 327[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
320difference between the contact position and the approaching tool position 328difference between the contact position and the approaching tool position
321could be used to derive tilt. 329could be used to derive tilt.
322[2] The list can of course be extended. 330[2] The list can of course be extended.
323[3] Multitouch X driver project: http://bitmath.org/code/multitouch/. 331[3] The mtdev project: http://bitmath.org/code/mtdev/.
324[4] See the section on event computation. 332[4] See the section on event computation.
325[5] See the section on finger tracking. 333[5] See the section on finger tracking.
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f4a37f842cfe..88668ae96945 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1302,6 +1302,7 @@ static const struct hid_device_id hid_blacklist[] = {
1302 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, 1302 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
1303 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, 1303 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
1304 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, 1304 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
1305 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
1305 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, 1306 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
1306 { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, 1307 { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
1307 { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, 1308 { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c
index 87878509f25e..16566fcc08a3 100644
--- a/drivers/hid/hid-egalax.c
+++ b/drivers/hid/hid-egalax.c
@@ -242,6 +242,8 @@ static const struct hid_device_id egalax_devices[] = {
242 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, 242 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
243 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, 243 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
244 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, 244 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
245 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
246 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
245 { } 247 { }
246}; 248};
247MODULE_DEVICE_TABLE(hid, egalax_devices); 249MODULE_DEVICE_TABLE(hid, egalax_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a95719b24756..0f150c72da7b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -198,6 +198,7 @@
198#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c 198#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c
199#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1 199#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1
200#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e 200#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e
201#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b
201 202
202#define USB_VENDOR_ID_ELECOM 0x056e 203#define USB_VENDOR_ID_ELECOM 0x056e
203#define USB_DEVICE_ID_ELECOM_BM084 0x0061 204#define USB_DEVICE_ID_ELECOM_BM084 0x0061
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 17660b1c8591..f8635b7b4295 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -678,6 +678,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
678#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) 678#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
679 switch (EVIOC_MASK_SIZE(cmd)) { 679 switch (EVIOC_MASK_SIZE(cmd)) {
680 680
681 case EVIOCGPROP(0):
682 return bits_to_user(dev->propbit, INPUT_PROP_MAX,
683 size, p, compat_mode);
684
681 case EVIOCGKEY(0): 685 case EVIOCGKEY(0):
682 return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode); 686 return bits_to_user(dev->key, KEY_MAX, size, p, compat_mode);
683 687
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3312e20016bf..9408dba2cd31 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1110,6 +1110,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
1110 seq_printf(seq, "%s ", handle->name); 1110 seq_printf(seq, "%s ", handle->name);
1111 seq_putc(seq, '\n'); 1111 seq_putc(seq, '\n');
1112 1112
1113 input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
1114
1113 input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX); 1115 input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
1114 if (test_bit(EV_KEY, dev->evbit)) 1116 if (test_bit(EV_KEY, dev->evbit))
1115 input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX); 1117 input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
@@ -1333,11 +1335,26 @@ static ssize_t input_dev_show_modalias(struct device *dev,
1333} 1335}
1334static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); 1336static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
1335 1337
1338static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
1339 int max, int add_cr);
1340
1341static ssize_t input_dev_show_properties(struct device *dev,
1342 struct device_attribute *attr,
1343 char *buf)
1344{
1345 struct input_dev *input_dev = to_input_dev(dev);
1346 int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
1347 INPUT_PROP_MAX, true);
1348 return min_t(int, len, PAGE_SIZE);
1349}
1350static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
1351
1336static struct attribute *input_dev_attrs[] = { 1352static struct attribute *input_dev_attrs[] = {
1337 &dev_attr_name.attr, 1353 &dev_attr_name.attr,
1338 &dev_attr_phys.attr, 1354 &dev_attr_phys.attr,
1339 &dev_attr_uniq.attr, 1355 &dev_attr_uniq.attr,
1340 &dev_attr_modalias.attr, 1356 &dev_attr_modalias.attr,
1357 &dev_attr_properties.attr,
1341 NULL 1358 NULL
1342}; 1359};
1343 1360
@@ -1471,7 +1488,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
1471{ 1488{
1472 int len; 1489 int len;
1473 1490
1474 if (add_uevent_var(env, "%s=", name)) 1491 if (add_uevent_var(env, "%s", name))
1475 return -ENOMEM; 1492 return -ENOMEM;
1476 1493
1477 len = input_print_bitmap(&env->buf[env->buflen - 1], 1494 len = input_print_bitmap(&env->buf[env->buflen - 1],
@@ -1537,6 +1554,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
1537 if (dev->uniq) 1554 if (dev->uniq)
1538 INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq); 1555 INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
1539 1556
1557 INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
1558
1540 INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX); 1559 INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);
1541 if (test_bit(EV_KEY, dev->evbit)) 1560 if (test_bit(EV_KEY, dev->evbit))
1542 INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX); 1561 INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index bea89722c4e9..82542a1c1098 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -680,6 +680,10 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
680 retval = uinput_set_bit(arg, swbit, SW_MAX); 680 retval = uinput_set_bit(arg, swbit, SW_MAX);
681 break; 681 break;
682 682
683 case UI_SET_PROPBIT:
684 retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
685 break;
686
683 case UI_SET_PHYS: 687 case UI_SET_PHYS:
684 if (udev->state == UIST_CREATED) { 688 if (udev->state == UIST_CREATED) {
685 retval = -EINVAL; 689 retval = -EINVAL;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index a977ef4c6625..da392c22fc6c 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -25,7 +25,7 @@
25 25
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/dmi.h> 27#include <linux/dmi.h>
28#include <linux/input.h> 28#include <linux/input/mt.h>
29#include <linux/serio.h> 29#include <linux/serio.h>
30#include <linux/libps2.h> 30#include <linux/libps2.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
@@ -279,6 +279,25 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
279 synaptics_mode_cmd(psmouse, priv->mode); 279 synaptics_mode_cmd(psmouse, priv->mode);
280} 280}
281 281
282static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
283{
284 static unsigned char param = 0xc8;
285 struct synaptics_data *priv = psmouse->private;
286
287 if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
288 return 0;
289
290 if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
291 return -1;
292 if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
293 return -1;
294
295 /* Advanced gesture mode also sends multi finger data */
296 priv->capabilities |= BIT(1);
297
298 return 0;
299}
300
282/***************************************************************************** 301/*****************************************************************************
283 * Synaptics pass-through PS/2 port support 302 * Synaptics pass-through PS/2 port support
284 ****************************************************************************/ 303 ****************************************************************************/
@@ -380,7 +399,9 @@ static void synaptics_pt_create(struct psmouse *psmouse)
380 * Functions to interpret the absolute mode packets 399 * Functions to interpret the absolute mode packets
381 ****************************************************************************/ 400 ****************************************************************************/
382 401
383static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) 402static int synaptics_parse_hw_state(const unsigned char buf[],
403 struct synaptics_data *priv,
404 struct synaptics_hw_state *hw)
384{ 405{
385 memset(hw, 0, sizeof(struct synaptics_hw_state)); 406 memset(hw, 0, sizeof(struct synaptics_hw_state));
386 407
@@ -397,6 +418,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
397 ((buf[0] & 0x04) >> 1) | 418 ((buf[0] & 0x04) >> 1) |
398 ((buf[3] & 0x04) >> 2)); 419 ((buf[3] & 0x04) >> 2));
399 420
421 if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
422 /* Gesture packet: (x, y, z) at half resolution */
423 priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
424 priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
425 priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
426 return 1;
427 }
428
400 hw->left = (buf[0] & 0x01) ? 1 : 0; 429 hw->left = (buf[0] & 0x01) ? 1 : 0;
401 hw->right = (buf[0] & 0x02) ? 1 : 0; 430 hw->right = (buf[0] & 0x02) ? 1 : 0;
402 431
@@ -452,6 +481,36 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
452 hw->left = (buf[0] & 0x01) ? 1 : 0; 481 hw->left = (buf[0] & 0x01) ? 1 : 0;
453 hw->right = (buf[0] & 0x02) ? 1 : 0; 482 hw->right = (buf[0] & 0x02) ? 1 : 0;
454 } 483 }
484
485 return 0;
486}
487
488static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
489{
490 input_mt_slot(dev, slot);
491 input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
492 if (active) {
493 input_report_abs(dev, ABS_MT_POSITION_X, x);
494 input_report_abs(dev, ABS_MT_POSITION_Y,
495 YMAX_NOMINAL + YMIN_NOMINAL - y);
496 }
497}
498
499static void synaptics_report_semi_mt_data(struct input_dev *dev,
500 const struct synaptics_hw_state *a,
501 const struct synaptics_hw_state *b,
502 int num_fingers)
503{
504 if (num_fingers >= 2) {
505 set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
506 set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
507 } else if (num_fingers == 1) {
508 set_slot(dev, 0, true, a->x, a->y);
509 set_slot(dev, 1, false, 0, 0);
510 } else {
511 set_slot(dev, 0, false, 0, 0);
512 set_slot(dev, 1, false, 0, 0);
513 }
455} 514}
456 515
457/* 516/*
@@ -466,7 +525,8 @@ static void synaptics_process_packet(struct psmouse *psmouse)
466 int finger_width; 525 int finger_width;
467 int i; 526 int i;
468 527
469 synaptics_parse_hw_state(psmouse->packet, priv, &hw); 528 if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
529 return;
470 530
471 if (hw.scroll) { 531 if (hw.scroll) {
472 priv->scroll += hw.scroll; 532 priv->scroll += hw.scroll;
@@ -488,7 +548,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
488 return; 548 return;
489 } 549 }
490 550
491 if (hw.z > 0) { 551 if (hw.z > 0 && hw.x > 1) {
492 num_fingers = 1; 552 num_fingers = 1;
493 finger_width = 5; 553 finger_width = 5;
494 if (SYN_CAP_EXTENDED(priv->capabilities)) { 554 if (SYN_CAP_EXTENDED(priv->capabilities)) {
@@ -512,6 +572,9 @@ static void synaptics_process_packet(struct psmouse *psmouse)
512 finger_width = 0; 572 finger_width = 0;
513 } 573 }
514 574
575 if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
576 synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);
577
515 /* Post events 578 /* Post events
516 * BTN_TOUCH has to be first as mousedev relies on it when doing 579 * BTN_TOUCH has to be first as mousedev relies on it when doing
517 * absolute -> relative conversion 580 * absolute -> relative conversion
@@ -519,7 +582,7 @@ static void synaptics_process_packet(struct psmouse *psmouse)
519 if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); 582 if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1);
520 if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); 583 if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0);
521 584
522 if (hw.z > 0) { 585 if (num_fingers > 0) {
523 input_report_abs(dev, ABS_X, hw.x); 586 input_report_abs(dev, ABS_X, hw.x);
524 input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); 587 input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
525 } 588 }
@@ -622,6 +685,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
622{ 685{
623 int i; 686 int i;
624 687
688 __set_bit(INPUT_PROP_POINTER, dev->propbit);
689
625 __set_bit(EV_ABS, dev->evbit); 690 __set_bit(EV_ABS, dev->evbit);
626 input_set_abs_params(dev, ABS_X, 691 input_set_abs_params(dev, ABS_X,
627 XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); 692 XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0);
@@ -629,6 +694,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
629 YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); 694 YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
630 input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); 695 input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
631 696
697 if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
698 __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
699 input_mt_init_slots(dev, 2);
700 input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
701 priv->x_max ?: XMAX_NOMINAL, 0, 0);
702 input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
703 priv->y_max ?: YMAX_NOMINAL, 0, 0);
704 }
705
632 if (SYN_CAP_PALMDETECT(priv->capabilities)) 706 if (SYN_CAP_PALMDETECT(priv->capabilities))
633 input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); 707 input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
634 708
@@ -663,6 +737,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
663 input_abs_set_res(dev, ABS_Y, priv->y_res); 737 input_abs_set_res(dev, ABS_Y, priv->y_res);
664 738
665 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { 739 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
740 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
666 /* Clickpads report only left button */ 741 /* Clickpads report only left button */
667 __clear_bit(BTN_RIGHT, dev->keybit); 742 __clear_bit(BTN_RIGHT, dev->keybit);
668 __clear_bit(BTN_MIDDLE, dev->keybit); 743 __clear_bit(BTN_MIDDLE, dev->keybit);
@@ -702,6 +777,11 @@ static int synaptics_reconnect(struct psmouse *psmouse)
702 return -1; 777 return -1;
703 } 778 }
704 779
780 if (synaptics_set_advanced_gesture_mode(psmouse)) {
781 printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
782 return -1;
783 }
784
705 return 0; 785 return 0;
706} 786}
707 787
@@ -799,6 +879,11 @@ int synaptics_init(struct psmouse *psmouse)
799 goto init_fail; 879 goto init_fail;
800 } 880 }
801 881
882 if (synaptics_set_advanced_gesture_mode(psmouse)) {
883 printk(KERN_ERR "Advanced gesture mode init failed.\n");
884 goto init_fail;
885 }
886
802 priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; 887 priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
803 888
804 printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", 889 printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 613a3652f98f..50e20e9da442 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -53,6 +53,7 @@
53#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) 53#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
54#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) 54#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100)
55#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) 55#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000)
56#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)
56 57
57/* synaptics modes query bits */ 58/* synaptics modes query bits */
58#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) 59#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
@@ -112,6 +113,8 @@ struct synaptics_data {
112 int scroll; 113 int scroll;
113 114
114 struct serio *pt_port; /* Pass-through serio port */ 115 struct serio *pt_port; /* Pass-through serio port */
116
117 struct synaptics_hw_state mt; /* current gesture packet */
115}; 118};
116 119
117void synaptics_module_init(void); 120void synaptics_module_init(void);
diff --git a/include/linux/input.h b/include/linux/input.h
index 53f873e8556c..6c407e553a40 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -91,6 +91,7 @@ struct input_keymap_entry {
91#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ 91#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
92#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ 92#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
93#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */ 93#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
94#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */
94 95
95#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */ 96#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */
96#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */ 97#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
@@ -108,6 +109,18 @@ struct input_keymap_entry {
108#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ 109#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
109 110
110/* 111/*
112 * Device properties and quirks
113 */
114
115#define INPUT_PROP_POINTER 0x00 /* needs a pointer */
116#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
117#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
118#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
119
120#define INPUT_PROP_MAX 0x1f
121#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
122
123/*
111 * Event types 124 * Event types
112 */ 125 */
113 126
@@ -1090,6 +1103,7 @@ struct ff_effect {
1090 * @phys: physical path to the device in the system hierarchy 1103 * @phys: physical path to the device in the system hierarchy
1091 * @uniq: unique identification code for the device (if device has it) 1104 * @uniq: unique identification code for the device (if device has it)
1092 * @id: id of the device (struct input_id) 1105 * @id: id of the device (struct input_id)
1106 * @propbit: bitmap of device properties and quirks
1093 * @evbit: bitmap of types of events supported by the device (EV_KEY, 1107 * @evbit: bitmap of types of events supported by the device (EV_KEY,
1094 * EV_REL, etc.) 1108 * EV_REL, etc.)
1095 * @keybit: bitmap of keys/buttons this device has 1109 * @keybit: bitmap of keys/buttons this device has
@@ -1173,6 +1187,8 @@ struct input_dev {
1173 const char *uniq; 1187 const char *uniq;
1174 struct input_id id; 1188 struct input_id id;
1175 1189
1190 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
1191
1176 unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; 1192 unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
1177 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; 1193 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
1178 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; 1194 unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 05f7fed2b173..d28c726ede4f 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -104,6 +104,7 @@ struct uinput_ff_erase {
104#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) 104#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
105#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) 105#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
106#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int) 106#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
107#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
107 108
108#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload) 109#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
109#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload) 110#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)