From: Gabriel M. Beddingfield <[email protected]>

This is a backport of c5f4dec1, implementing the API, but not touching
the existing drivers.  Comments on original commit:

    From c5f4dec1ceb6ab773bbbefbe64a7c990c7d6b17f Mon Sep 17 00:00:00 2001
    From: Henrik Rydberg <[email protected]>
    Date: Wed, 15 Dec 2010 13:50:34 +0100
    Subject: [PATCH] input: mt: Move tracking and pointer emulation to input-mt

    The drivers using the type B protocol all report tracking information
    the same way. The contact id is semantically equivalent to
    ABS_MT_SLOT, and the handling of ABS_MT_TRACKING_ID only complicates
    the driver. The situation can be improved upon by providing a common
    pointer emulation code, thereby removing the need for the tracking id
    in the driver.  This patch moves all tracking event handling over to
    the input core, simplifying both the existing drivers and the ones
    currently in preparation.

    Acked-by: Ping Cheng <[email protected]>
    Acked-by: Jiri Kosina <[email protected]>
    Signed-off-by: Henrik Rydberg <[email protected]>

Signed-off-by: Gabriel M. Beddingfield <[email protected]>
---
 drivers/input/input.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/input.h |   13 ++++++
 2 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 968f5a3..e2200eb 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -31,6 +31,7 @@ MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
 #define INPUT_DEVICES  256
+#define TRKID_SGN      ((TRKID_MAX + 1) >> 1)
 
 static LIST_HEAD(input_dev_list);
 static LIST_HEAD(input_handler_list);
@@ -1715,8 +1716,10 @@ EXPORT_SYMBOL(input_free_device);
  * @num_slots: number of slots used by the device
  *
  * This function allocates all necessary memory for MT slot handling in the
- * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
- * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
+ * in the input device, prepares the ABS_MT_SLOT and
+ * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * May be called repeatedly. Returns -EINVAL if attempting to
+ * reinitialize with a different number of slots.
  */
 int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
 {
@@ -1733,6 +1736,7 @@ int input_mt_create_slots(struct input_dev *dev, unsigned 
int num_slots)
 
        dev->mtsize = num_slots;
        input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
+       input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
        input_set_events_per_packet(dev, 6 * num_slots);
 
        /* Mark slots as 'unused' */
@@ -1756,10 +1760,113 @@ void input_mt_destroy_slots(struct input_dev *dev)
        dev->mt = NULL;
        dev->mtsize = 0;
        dev->slot = 0;
+       dev->trkid = 0;
 }
 EXPORT_SYMBOL(input_mt_destroy_slots);
 
 /**
+ * input_mt_report_slot_state() - report contact state
+ * @dev: input device with allocated MT slots
+ * @tool_type: the tool type to use in this slot
+ * @active: true if contact is active, false otherwise
+ *
+ * Reports a contact via ABS_MT_TRACKING_ID, and optionally
+ * ABS_MT_TOOL_TYPE. If active is true and the slot is currently
+ * inactive, or if the tool type is changed, a new tracking id is
+ * assigned to the slot. The tool type is only reported if the
+ * corresponding absbit field is set.
+ */
+void input_mt_report_slot_state(struct input_dev *dev,
+                               unsigned int tool_type, bool active)
+{
+       struct input_mt_slot *mt;
+       int id;
+
+       if (!dev->mt || !active) {
+               input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+               return;
+       }
+
+       mt = &dev->mt[dev->slot];
+       id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
+       if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
+               id = input_mt_new_trkid(dev);
+
+       input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
+       input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
+}
+EXPORT_SYMBOL(input_mt_report_slot_state);
+
+/**
+ * input_mt_report_finger_count() - report contact count
+ * @dev: input device with allocated MT slots
+ * @count: the number of contacts
+ *
+ * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
+ * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
+ *
+ * The input core ensures only the KEY events already setup for
+ * this device will produce output.
+ */
+void input_mt_report_finger_count(struct input_dev *dev, int count)
+{
+       input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
+       input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
+       input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
+       input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
+}
+EXPORT_SYMBOL(input_mt_report_finger_count);
+
+/**
+ * input_mt_report_pointer_emulation() - common pointer emulation
+ * @dev: input device with allocated MT slots
+ * @use_count: report number of active contacts as finger count
+ *
+ * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
+ * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
+ *
+ * The input core ensures only the KEY and ABS axes already setup for
+ * this device will produce output.
+ */
+void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
+{
+       struct input_mt_slot *oldest = 0;
+       int oldid = dev->trkid;
+       int count = 0;
+       int i;
+
+       for (i = 0; i < dev->mtsize; ++i) {
+               struct input_mt_slot *ps = &dev->mt[i];
+               int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+
+               if (id < 0)
+                       continue;
+               if ((id - oldid) & TRKID_SGN) {
+                       oldest = ps;
+                       oldid = id;
+               }
+               count++;
+       }
+
+       input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
+       if (use_count)
+               input_mt_report_finger_count(dev, count);
+
+       if (oldest) {
+               int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
+               int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
+               int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
+
+               input_event(dev, EV_ABS, ABS_X, x);
+               input_event(dev, EV_ABS, ABS_Y, y);
+               input_event(dev, EV_ABS, ABS_PRESSURE, p);
+       } else {
+               input_event(dev, EV_ABS, ABS_PRESSURE, 0);
+       }
+}
+EXPORT_SYMBOL(input_mt_report_pointer_emulation);
+
+/**
  * input_set_capability - mark device as capable of a certain event
  * @dev: device that is capable of emitting or accepting event
  * @type: type of the event (EV_KEY, EV_REL, etc...)
diff --git a/include/linux/input.h b/include/linux/input.h
index bc121a8..0b89aa5 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -873,6 +873,12 @@ struct input_keymap_entry {
  */
 #define MT_TOOL_FINGER         0
 #define MT_TOOL_PEN            1
+#define MT_TOOL_MAX            1
+
+/*
+ * MT Track ID
+ */
+#define TRKID_MAX              0xffff
 
 /*
  * Values describing the status of a force-feedback effect
@@ -1155,6 +1161,7 @@ struct input_mt_slot {
  *     of tracked contacts
  * @mtsize: number of MT slots the device uses
  * @slot: MT slot currently being transmitted
+ * @trkid: stores MT tracking ID for the current contact
  * @absinfo: array of &struct input_absinfo elements holding information
  *     about absolute axes (current value, min, max, flat, fuzz,
  *     resolution)
@@ -1239,6 +1246,7 @@ struct input_dev {
        struct input_mt_slot *mt;
        int mtsize;
        int slot;
+       int trkid;
 
        struct input_absinfo *absinfo;
 
@@ -1488,6 +1496,11 @@ static inline void input_mt_sync(struct input_dev *dev)
        input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
 }
 
+static inline int input_mt_new_trkid(struct input_dev *dev)
+{
+       return dev->trkid++ & TRKID_MAX;
+}
+
 static inline void input_mt_slot(struct input_dev *dev, int slot)
 {
        input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
-- 
1.7.0.4

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to