aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/input-mt.c70
-rw-r--r--include/linux/input/mt.h9
2 files changed, 77 insertions, 2 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 1985f27f427a..96cc2e2a9be2 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -14,6 +14,14 @@
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
+static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
+{
+ if (dev->absinfo && test_bit(src, dev->absbit)) {
+ dev->absinfo[dst] = dev->absinfo[src];
+ dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
+ }
+}
+
/**
* input_mt_init_slots() - initialize MT input slots
* @dev: input device supporting MT events and finger tracking
@@ -45,6 +53,28 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int 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);
+ if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
+ __set_bit(EV_KEY, dev->evbit);
+ __set_bit(BTN_TOUCH, dev->keybit);
+
+ copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
+ copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
+ copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
+ }
+ if (flags & INPUT_MT_POINTER) {
+ __set_bit(BTN_TOOL_FINGER, dev->keybit);
+ __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+ if (num_slots >= 3)
+ __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
+ if (num_slots >= 4)
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ if (num_slots >= 5)
+ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+ __set_bit(INPUT_PROP_POINTER, dev->propbit);
+ }
+ if (flags & INPUT_MT_DIRECT)
+ __set_bit(INPUT_PROP_DIRECT, dev->propbit);
+
/* Mark slots as 'unused' */
for (i = 0; i < num_slots; i++)
input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
@@ -87,12 +117,17 @@ void input_mt_report_slot_state(struct input_dev *dev,
struct input_mt_slot *slot;
int id;
- if (!mt || !active) {
+ if (!mt)
+ return;
+
+ slot = &mt->slots[mt->slot];
+ slot->frame = mt->frame;
+
+ if (!active) {
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
return;
}
- slot = &mt->slots[mt->slot];
id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
id = input_mt_new_trkid(mt);
@@ -177,3 +212,34 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
}
}
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
+
+/**
+ * input_mt_sync_frame() - synchronize mt frame
+ * @dev: input device with allocated MT slots
+ *
+ * Close the frame and prepare the internal state for a new one.
+ * Depending on the flags, marks unused slots as inactive and performs
+ * pointer emulation.
+ */
+void input_mt_sync_frame(struct input_dev *dev)
+{
+ struct input_mt *mt = dev->mt;
+ struct input_mt_slot *s;
+
+ if (!mt)
+ return;
+
+ if (mt->flags & INPUT_MT_DROP_UNUSED) {
+ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+ if (s->frame == mt->frame)
+ continue;
+ input_mt_slot(dev, s - mt->slots);
+ input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ }
+ }
+
+ input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
+
+ mt->frame++;
+}
+EXPORT_SYMBOL(input_mt_sync_frame);
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index 53f5bf168ff9..94989189878d 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -15,12 +15,17 @@
#define TRKID_MAX 0xffff
+#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */
+#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */
+#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */
/**
* struct input_mt_slot - represents the state of an input MT slot
* @abs: holds current values of ABS_MT axes for this slot
+ * @frame: last frame at which input_mt_report_slot_state() was called
*/
struct input_mt_slot {
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
+ unsigned int frame;
};
/**
@@ -29,6 +34,7 @@ struct input_mt_slot {
* @num_slots: number of MT slots the device uses
* @slot: MT slot currently being transmitted
* @flags: input_mt operation flags
+ * @frame: increases every time input_mt_sync_frame() is called
* @slots: array of slots holding current values of tracked contacts
*/
struct input_mt {
@@ -36,6 +42,7 @@ struct input_mt {
int num_slots;
int slot;
unsigned int flags;
+ unsigned int frame;
struct input_mt_slot slots[];
};
@@ -81,4 +88,6 @@ void input_mt_report_slot_state(struct input_dev *dev,
void input_mt_report_finger_count(struct input_dev *dev, int count);
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
+void input_mt_sync_frame(struct input_dev *dev);
+
#endif