diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-12-27 20:33:20 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-12-27 20:33:20 -0500 |
commit | 5c461b913a16aed8afa285a1d00414791a9afe33 (patch) | |
tree | 95c7d32fcb899240e8bc5ab5bfac20d259a81b46 | |
parent | ef11e701f32fb0cd5c5f0f6fb9a9e28fab151219 (diff) | |
parent | 4f56ce929cab45a3a6e1a81700da52bb9bdbfc0f (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.txt | 44 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-egalax.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
-rw-r--r-- | drivers/input/evdev.c | 4 | ||||
-rw-r--r-- | drivers/input/input.c | 21 | ||||
-rw-r--r-- | drivers/input/misc/uinput.c | 4 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 95 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 3 | ||||
-rw-r--r-- | include/linux/input.h | 16 | ||||
-rw-r--r-- | include/linux/uinput.h | 1 |
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 @@ | |||
1 | Multi-touch (MT) Protocol | 1 | Multi-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 | ||
6 | Introduction | 6 | Introduction |
@@ -169,12 +169,16 @@ described by adding the MINOR parameters, such that MAJOR and MINOR are the | |||
169 | major and minor axis of an ellipse. Finally, the orientation of the oval | 169 | major and minor axis of an ellipse. Finally, the orientation of the oval |
170 | shape can be describe with the ORIENTATION parameter. | 170 | shape can be describe with the ORIENTATION parameter. |
171 | 171 | ||
172 | For type A devices, further specification of the touch shape is possible | ||
173 | via ABS_MT_BLOB_ID. | ||
174 | |||
172 | The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a | 175 | The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a |
173 | contact or a pen or something else. Devices with more granular information | 176 | finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event |
174 | may specify general shapes as blobs, i.e., as a sequence of rectangular | 177 | may be used to track identified contacts over time [5]. |
175 | shapes grouped together by an ABS_MT_BLOB_ID. Finally, for the few devices | 178 | |
176 | that currently support it, the ABS_MT_TRACKING_ID event may be used to | 179 | In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are |
177 | report contact tracking from hardware [5]. | 180 | implicitly handled by input core; drivers should instead call |
181 | input_mt_report_slot_state(). | ||
178 | 182 | ||
179 | 183 | ||
180 | Event Semantics | 184 | Event Semantics |
@@ -247,21 +251,24 @@ ABS_MT_TOOL_TYPE | |||
247 | The type of approaching tool. A lot of kernel drivers cannot distinguish | 251 | The type of approaching tool. A lot of kernel drivers cannot distinguish |
248 | between different tool types, such as a finger or a pen. In such cases, the | 252 | between different tool types, such as a finger or a pen. In such cases, the |
249 | event should be omitted. The protocol currently supports MT_TOOL_FINGER and | 253 | event should be omitted. The protocol currently supports MT_TOOL_FINGER and |
250 | MT_TOOL_PEN [2]. | 254 | MT_TOOL_PEN [2]. For type B devices, this event is handled by input core; |
255 | drivers should instead use input_mt_report_slot_state(). | ||
251 | 256 | ||
252 | ABS_MT_BLOB_ID | 257 | ABS_MT_BLOB_ID |
253 | 258 | ||
254 | The BLOB_ID groups several packets together into one arbitrarily shaped | 259 | The BLOB_ID groups several packets together into one arbitrarily shaped |
255 | contact. This is a low-level anonymous grouping for type A devices, and | 260 | contact. The sequence of points forms a polygon which defines the shape of |
261 | the contact. This is a low-level anonymous grouping for type A devices, and | ||
256 | should not be confused with the high-level trackingID [5]. Most type A | 262 | should not be confused with the high-level trackingID [5]. Most type A |
257 | devices do not have blob capability, so drivers can safely omit this event. | 263 | devices do not have blob capability, so drivers can safely omit this event. |
258 | 264 | ||
259 | ABS_MT_TRACKING_ID | 265 | ABS_MT_TRACKING_ID |
260 | 266 | ||
261 | The TRACKING_ID identifies an initiated contact throughout its life cycle | 267 | The 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 |
263 | TRACKING_ID should be large enough to ensure unique identification of a | 269 | unique identification of a contact maintained over an extended period of |
264 | contact maintained over an extended period of time. | 270 | time. For type B devices, this event is handled by input core; drivers |
271 | should instead use input_mt_report_slot_state(). | ||
265 | 272 | ||
266 | 273 | ||
267 | Event Computation | 274 | Event Computation |
@@ -308,18 +315,19 @@ and with ORIENTATION, one can detect twisting of fingers. | |||
308 | Notes | 315 | Notes |
309 | ----- | 316 | ----- |
310 | 317 | ||
311 | In order to stay compatible with existing applications, the data | 318 | In order to stay compatible with existing applications, the data reported |
312 | reported in a finger packet must not be recognized as single-touch | 319 | in a finger packet must not be recognized as single-touch events. |
313 | events. In addition, all finger data must bypass input filtering, | 320 | |
314 | since subsequent events of the same type refer to different fingers. | 321 | For type A devices, all finger data bypasses input filtering, since |
322 | subsequent events of the same type refer to different fingers. | ||
315 | 323 | ||
316 | The first kernel driver to utilize the MT protocol is the bcm5974 driver, | 324 | For example usage of the type A protocol, see the bcm5974 driver. For |
317 | where examples can be found. | 325 | example 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 |
320 | difference between the contact position and the approaching tool position | 328 | difference between the contact position and the approaching tool position |
321 | could be used to derive tilt. | 329 | could 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 | }; |
247 | MODULE_DEVICE_TABLE(hid, egalax_devices); | 249 | MODULE_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 | } |
1334 | static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 1336 | static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
1335 | 1337 | ||
1338 | static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | ||
1339 | int max, int add_cr); | ||
1340 | |||
1341 | static 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 | } | ||
1350 | static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL); | ||
1351 | |||
1336 | static struct attribute *input_dev_attrs[] = { | 1352 | static 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 | ||
282 | static 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, ¶m, 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 | ||
383 | static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) | 402 | static 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 | |||
488 | static 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 | |||
499 | static 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 | ||
117 | void synaptics_module_init(void); | 120 | void 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) |