LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues
@ 2015-01-19 20:53 Benjamin Tissoires
2015-01-19 20:53 ` [RFC 1/6] Input: mt: make input_mt_assign_slots() a little bit more readable Benjamin Tissoires
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
Hi,
Well, I am posting this as an RFC for 2 reasons:
- I could not end up in a complete documentation on how the in-kernel tracking
was working (patches 1/6 to 5/6)
- I introduce a new input-mt API symbol, so I am pretty sure there will be some
changes requested. (path 6/6)
Anyway, this is the second part of the jumping cursors issue reported few months
ago:
https://bugs.freedesktop.org/show_bug.cgi?id=76722
Henrik if you have any pointers on how mathematically the reduced cost matrix
and the adjust dual function works, I think that should be enough to document
the code. I gave up trying to understand by hand (or with breakpoints), and all
I know is that it works.
Thanks for your feedback,
Cheers,
Benjamin
Benjamin Tissoires (6):
Input: mt: make input_mt_assign_slots() a little bit more readable
Input: mt: Document input_mt_set_slots()
Input: mt: document input_mt_set_matrix()
Input: mt: document find_reduced_matrix()
Input: mt: document adjust_dual()
Input: mt: introduce dmax in in-kernel tracking
drivers/input/input-mt.c | 184 +++++++++++++++++++++++++++++++++-------
drivers/input/mouse/synaptics.c | 3 +-
include/linux/input/mt.h | 4 +
3 files changed, 161 insertions(+), 30 deletions(-)
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 1/6] Input: mt: make input_mt_assign_slots() a little bit more readable
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 20:53 ` [RFC 2/6] Input: mt: Document input_mt_set_slots() Benjamin Tissoires
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
Rename "nrc" into "n_elems" and explicitly name the number of
rows and the number of columns.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index fbe29fc..b6ee42a 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -404,7 +404,7 @@ int input_mt_assign_slots(struct input_dev *dev, int *slots,
const struct input_mt_pos *pos, int num_pos)
{
struct input_mt *mt = dev->mt;
- int nrc;
+ int n_elems, n_rows, n_columns;
if (!mt || !mt->red)
return -ENXIO;
@@ -413,8 +413,10 @@ int input_mt_assign_slots(struct input_dev *dev, int *slots,
if (num_pos < 1)
return 0;
- nrc = input_mt_set_matrix(mt, pos, num_pos);
- find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc);
+ n_elems = input_mt_set_matrix(mt, pos, num_pos);
+ n_rows = n_elems / num_pos;
+ n_columns = num_pos;
+ find_reduced_matrix(mt->red, n_columns, n_rows, n_elems);
input_mt_set_slots(mt, slots, num_pos);
return 0;
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 2/6] Input: mt: Document input_mt_set_slots()
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
2015-01-19 20:53 ` [RFC 1/6] Input: mt: make input_mt_assign_slots() a little bit more readable Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 20:53 ` [RFC 3/6] Input: mt: document input_mt_set_matrix() Benjamin Tissoires
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
Renamed "w" into "red_cost_matrix" for readability.
Add docs and comments to detail what the code is expected to do.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index b6ee42a..b269113 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -359,23 +359,41 @@ static int input_mt_set_matrix(struct input_mt *mt,
return w - mt->red;
}
+/**
+ * input_mt_set_slots() - assign slots to the list of pos thanks to the reduced
+ * cost matrix
+ * @mt: the input_mt handle of the current device
+ * @slots: the slot assignment to be filled
+ * @num_pos: number of positions
+ *
+ * For each given touch in pos, try to match the touch to a previous one.
+ * Then, assign new slots to those who were not a match with the previously
+ * sent slots.
+ */
static void input_mt_set_slots(struct input_mt *mt,
int *slots, int num_pos)
{
struct input_mt_slot *s;
- int *w = mt->red, *p;
+ int *red_cost_matrix = mt->red;
+ int *p;
+ /* first initialise the output values to -1 */
for (p = slots; p != slots + num_pos; p++)
*p = -1;
+ /* for each currently active slot, match it with one of the touch
+ * in the pos array */
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (!input_mt_is_active(s))
continue;
for (p = slots; p != slots + num_pos; p++)
- if (*w++ < 0)
+ if (*red_cost_matrix++ < 0)
+ /* we have a match, store the slot value
+ * in pos[i] */
*p = s - mt->slots;
}
+ /* for each unassigned touch in pos, assign a new slot for it */
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (input_mt_is_active(s))
continue;
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 3/6] Input: mt: document input_mt_set_matrix()
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
2015-01-19 20:53 ` [RFC 1/6] Input: mt: make input_mt_assign_slots() a little bit more readable Benjamin Tissoires
2015-01-19 20:53 ` [RFC 2/6] Input: mt: Document input_mt_set_slots() Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 20:53 ` [RFC 4/6] Input: mt: document find_reduced_matrix() Benjamin Tissoires
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
Document what the function is about.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index b269113..0b98ac7 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -337,6 +337,21 @@ static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
}
}
+/**
+ * input_mt_set_matrix() - fill the reduced cost matrix for in-kernel tracking
+ * @mt: the input_mt handle of the current device
+ * @pos: the position array to match
+ * @num_pos: number of positions
+ *
+ * Fills the reduced cost matrix by putting in each element the square of the
+ * distance from one of the touch to each elements of the position array to
+ * match.
+ *
+ * The matrix is a reduced one, so it is filled as:
+ * w[i * num_pos + p] == distance(active_slot(i), pos[p])
+ *
+ * Returns the number of elements in the reduced matrix.
+ */
static int input_mt_set_matrix(struct input_mt *mt,
const struct input_mt_pos *pos, int num_pos)
{
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 4/6] Input: mt: document find_reduced_matrix()
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
` (2 preceding siblings ...)
2015-01-19 20:53 ` [RFC 3/6] Input: mt: document input_mt_set_matrix() Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 20:53 ` [RFC 5/6] Input: mt: document adjust_dual() Benjamin Tissoires
2015-01-19 20:53 ` [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking Benjamin Tissoires
5 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
find_reduced_matrix() is really cryptic right now.
To try to understand what the function does, replace the variable names
with the following:
nrc -> n_elems
nr -> n_rows
nc -> n_columns
Also add a partial doc that needs to be filled by someone who knows
what the function is actually doing.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 0b98ac7..e43c33c 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -322,16 +322,32 @@ static int adjust_dual(int *begin, int step, int *end, int eq)
return (c < s && s <= 0) || (f >= 0 && f < c);
}
-static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
+/**
+ * find_reduced_matrix() -
+ * @matrix: the current reduced cost matrix (to be changed in place)
+ * @n_rows: number of rows in the matrix
+ * @n_columns: number of columns in the matrix
+ * @n_elems: number of elements in the matrix (should be n_rows * n_columns)
+ *
+ * FIXME -- can someone tell what this function does???
+ */
+static void find_reduced_matrix(int *matrix, int n_rows, int n_columns,
+ int n_elems)
{
int i, k, sum;
- for (k = 0; k < nrc; k++) {
- for (i = 0; i < nr; i++)
- adjust_dual(w + i, nr, w + i + nrc, nr <= nc);
+ for (k = 0; k < n_elems; k++) {
+ for (i = 0; i < n_rows; i++)
+ adjust_dual(matrix + i,
+ n_rows,
+ matrix + i + n_elems,
+ n_rows <= n_columns);
sum = 0;
- for (i = 0; i < nrc; i += nr)
- sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr);
+ for (i = 0; i < n_elems; i += n_rows)
+ sum += adjust_dual(matrix + i,
+ 1,
+ matrix + i + n_rows,
+ n_columns <= n_rows);
if (!sum)
break;
}
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 5/6] Input: mt: document adjust_dual()
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
` (3 preceding siblings ...)
2015-01-19 20:53 ` [RFC 4/6] Input: mt: document find_reduced_matrix() Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 20:53 ` [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking Benjamin Tissoires
5 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
adjust_dual() is really cryptic right now.
To try to understand what the function does, replace the variable names
with the following:
f -> first
p -> cur
s -> stop
c -> center
Also add a partial doc that needs to be filled by someone who knows
what the function is actually doing.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 44 ++++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index e43c33c..c7b3752 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -293,33 +293,45 @@ void input_mt_sync_frame(struct input_dev *dev)
}
EXPORT_SYMBOL(input_mt_sync_frame);
+/**
+ * adjust_dual() -
+ * @begin
+ * @step
+ * @end
+ * @eq
+ *
+ * FIXME -- can someone tell what this function does???
+ */
static int adjust_dual(int *begin, int step, int *end, int eq)
{
- int f, *p, s, c;
+ int first, *cur, stop, center;
if (begin == end)
return 0;
- f = *begin;
- p = begin + step;
- s = p == end ? f + 1 : *p;
+ first = *begin;
+ cur = begin + step;
+ stop = cur == end ? first + 1 : *cur;
- for (; p != end; p += step)
- if (*p < f)
- s = f, f = *p;
- else if (*p < s)
- s = *p;
+ for (; cur != end; cur += step) {
+ if (*cur < first) {
+ stop = first;
+ first = *cur;
+ } else if (*cur < stop) {
+ stop = *cur;
+ }
+ }
- c = (f + s + 1) / 2;
- if (c == 0 || (c > 0 && !eq))
+ center = (first + stop + 1) / 2;
+ if (center == 0 || (center > 0 && !eq))
return 0;
- if (s < 0)
- c *= 2;
+ if (stop < 0)
+ center *= 2;
- for (p = begin; p != end; p += step)
- *p -= c;
+ for (cur = begin; cur != end; cur += step)
+ *cur -= center;
- return (c < s && s <= 0) || (f >= 0 && f < c);
+ return (center < stop && stop <= 0) || (first >= 0 && first < center);
}
/**
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
` (4 preceding siblings ...)
2015-01-19 20:53 ` [RFC 5/6] Input: mt: document adjust_dual() Benjamin Tissoires
@ 2015-01-19 20:53 ` Benjamin Tissoires
2015-01-19 21:03 ` Benjamin Tissoires
5 siblings, 1 reply; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 20:53 UTC (permalink / raw)
To: Henrik Rydberg, Dmitry Torokhov, Hans de Goede
Cc: Peter Hutterer, linux-input, linux-kernel
When tapping a clickpad with two fingers, there is a chance that the sensor
sees first only one finger, and at the next scan only the second one.
In this case, the sensors says that there has been only one finger
on the clickpad, which moved really fast between two scans.
We can try to counter this by adding a limit to what an actual finger
can move between 2 scans.
We can try to provide a reasonable distance of 1cm between two scans for
one finger. This is what is used in the synaptcs.c portion of the patch.
However, this is not really accurate because the resolution in X and in Y
differs. But heh, that's how the in-kernel tracking works right now, and
its job is quite good even with this approximation.
Once a driver has set the maximum distance for a jump of a finger between
two scans, we can tell the in-kernel tracking to dissociate the slots
and the touch with input_mt_check_slots().
In order not to penalize better sensors, this parameter is not
automatically enabled, but each driver has to manually set it to a
reasonable value.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76722
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/input-mt.c | 67 +++++++++++++++++++++++++++++++++++++++--
drivers/input/mouse/synaptics.c | 3 +-
include/linux/input/mt.h | 4 +++
3 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index c7b3752..d326262 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -403,9 +403,51 @@ static int input_mt_set_matrix(struct input_mt *mt,
}
/**
+ * input_mt_check_slots() - validate the slot assignments
+ * @mt: the input_mt handle of the current device
+ * @pos: the position array to match
+ * @slots: the slot assignment to be filled
+ * @num_pos: number of positions
+ *
+ * For each assigned touch in pos, check if the distance between this touch
+ * and the previously reported position is not too big.
+ * If it is too big, break the assignment by resetting the slot value to -1.
+ * While syncing the frame, the previously matched slot will be freed, and
+ * a new one will be assigned in input_mt_set_slots().
+ *
+ * The "too big" parameter is stored in mt->dmax2.
+ */
+static void input_mt_check_slots(struct input_mt *mt,
+ const struct input_mt_pos *pos, int *slots,
+ int num_pos)
+{
+ struct input_mt_slot *s;
+ int *p;
+ int i, x, y, d2, dx, dy;
+ struct input_mt_pos *mt_pos;
+
+ if (!mt->dmax2)
+ return;
+
+ for (i = 0; i < num_pos; i++) {
+ mt_pos = pos + i;
+ p = slots + i;
+ s = mt->slots + *p;
+ x = input_mt_get_value(s, ABS_MT_POSITION_X);
+ y = input_mt_get_value(s, ABS_MT_POSITION_Y);
+ dx = x - mt_pos->x;
+ dy = y - mt_pos->y;
+ d2 = dx * dx + dy * dy;
+ if (d2 >= mt->dmax2)
+ *p = -1;
+ }
+}
+
+/**
* input_mt_set_slots() - assign slots to the list of pos thanks to the reduced
* cost matrix
* @mt: the input_mt handle of the current device
+ * @pos: the position array to match
* @slots: the slot assignment to be filled
* @num_pos: number of positions
*
@@ -414,7 +456,8 @@ static int input_mt_set_matrix(struct input_mt *mt,
* sent slots.
*/
static void input_mt_set_slots(struct input_mt *mt,
- int *slots, int num_pos)
+ const struct input_mt_pos *pos, int *slots,
+ int num_pos)
{
struct input_mt_slot *s;
int *red_cost_matrix = mt->red;
@@ -436,6 +479,8 @@ static void input_mt_set_slots(struct input_mt *mt,
*p = s - mt->slots;
}
+ input_mt_check_slots(mt, pos, slots, num_pos);
+
/* for each unassigned touch in pos, assign a new slot for it */
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (input_mt_is_active(s))
@@ -478,13 +523,31 @@ int input_mt_assign_slots(struct input_dev *dev, int *slots,
n_rows = n_elems / num_pos;
n_columns = num_pos;
find_reduced_matrix(mt->red, n_columns, n_rows, n_elems);
- input_mt_set_slots(mt, slots, num_pos);
+ input_mt_set_slots(mt, pos, slots, num_pos);
return 0;
}
EXPORT_SYMBOL(input_mt_assign_slots);
/**
+ * input_mt_set_dmax_tracking() - enhance tracking
+ * @dev: input device with allocated MT slots
+ * @dmax: the max distance between two touches to be considered as the same
+ *
+ * Enhance the in-kernel tracking by providing a maximum distance between
+ * 2 touches to be considered as the same slot.
+ * The stored value is the square of the provided distance to ease the tests
+ * later on. The input distance has to be given in the device coordinate system.
+ */
+void input_mt_set_dmax_tracking(struct input_dev *dev, int dmax)
+{
+ struct input_mt *mt = dev->mt;
+
+ mt->dmax2 = dmax * dmax;
+}
+EXPORT_SYMBOL(input_mt_set_dmax_tracking);
+
+/**
* input_mt_get_slot_by_key() - return slot matching key
* @dev: input device with allocated MT slots
* @key: the key of the sought slot
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index f89de89..95c15451 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1077,7 +1077,8 @@ static void set_input_params(struct psmouse *psmouse,
ABS_MT_POSITION_Y);
/* Image sensors can report per-contact pressure */
input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
- input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK);
+ input_mt_init_slots(dev, 4, INPUT_MT_POINTER | INPUT_MT_TRACK);
+ input_mt_set_dmax_tracking(dev, 10 * priv->x_res);
/* Image sensors can signal 4 and 5 finger clicks */
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
index f583ff6..c4b35c4 100644
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -41,6 +41,7 @@ struct input_mt_slot {
* @flags: input_mt operation flags
* @frame: increases every time input_mt_sync_frame() is called
* @red: reduced cost matrix for in-kernel tracking
+ * @dmax2: max (squared) distance between 2 points when using in-kernel tracking
* @slots: array of slots holding current values of tracked contacts
*/
struct input_mt {
@@ -50,6 +51,7 @@ struct input_mt {
unsigned int flags;
unsigned int frame;
int *red;
+ int dmax2;
struct input_mt_slot slots[];
};
@@ -100,6 +102,8 @@ static inline bool input_is_mt_axis(int axis)
return axis == ABS_MT_SLOT || input_is_mt_value(axis);
}
+void input_mt_set_dmax_tracking(struct input_dev *dev, int dmax);
+
void input_mt_report_slot_state(struct input_dev *dev,
unsigned int tool_type, bool active);
--
2.1.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking
2015-01-19 20:53 ` [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking Benjamin Tissoires
@ 2015-01-19 21:03 ` Benjamin Tissoires
0 siblings, 0 replies; 8+ messages in thread
From: Benjamin Tissoires @ 2015-01-19 21:03 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Henrik Rydberg, Dmitry Torokhov, Hans de Goede, Peter Hutterer,
linux-input, linux-kernel
On Mon, Jan 19, 2015 at 3:53 PM, Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
> When tapping a clickpad with two fingers, there is a chance that the sensor
> sees first only one finger, and at the next scan only the second one.
> In this case, the sensors says that there has been only one finger
> on the clickpad, which moved really fast between two scans.
>
> We can try to counter this by adding a limit to what an actual finger
> can move between 2 scans.
> We can try to provide a reasonable distance of 1cm between two scans for
> one finger. This is what is used in the synaptcs.c portion of the patch.
>
> However, this is not really accurate because the resolution in X and in Y
> differs. But heh, that's how the in-kernel tracking works right now, and
> its job is quite good even with this approximation.
>
> Once a driver has set the maximum distance for a jump of a finger between
> two scans, we can tell the in-kernel tracking to dissociate the slots
> and the touch with input_mt_check_slots().
>
> In order not to penalize better sensors, this parameter is not
> automatically enabled, but each driver has to manually set it to a
> reasonable value.
>
> Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76722
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
> drivers/input/input-mt.c | 67 +++++++++++++++++++++++++++++++++++++++--
> drivers/input/mouse/synaptics.c | 3 +-
> include/linux/input/mt.h | 4 +++
> 3 files changed, 71 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
> index c7b3752..d326262 100644
> --- a/drivers/input/input-mt.c
> +++ b/drivers/input/input-mt.c
> @@ -403,9 +403,51 @@ static int input_mt_set_matrix(struct input_mt *mt,
> }
>
> /**
> + * input_mt_check_slots() - validate the slot assignments
> + * @mt: the input_mt handle of the current device
> + * @pos: the position array to match
> + * @slots: the slot assignment to be filled
> + * @num_pos: number of positions
> + *
> + * For each assigned touch in pos, check if the distance between this touch
> + * and the previously reported position is not too big.
> + * If it is too big, break the assignment by resetting the slot value to -1.
> + * While syncing the frame, the previously matched slot will be freed, and
> + * a new one will be assigned in input_mt_set_slots().
> + *
> + * The "too big" parameter is stored in mt->dmax2.
> + */
> +static void input_mt_check_slots(struct input_mt *mt,
> + const struct input_mt_pos *pos, int *slots,
> + int num_pos)
> +{
> + struct input_mt_slot *s;
> + int *p;
> + int i, x, y, d2, dx, dy;
> + struct input_mt_pos *mt_pos;
Grmbl... checkpatch.pl complained about a missing line between the
declarations and the actual code (I first declared mt_pos within the
for loop). So I re-scrambled the things, and of course I forget to
re-add the "const" qualifer. So this line shows a pretty warning which
will be fixed in v2 :(
Cheers,
Benjamin
> +
> + if (!mt->dmax2)
> + return;
> +
> + for (i = 0; i < num_pos; i++) {
> + mt_pos = pos + i;
> + p = slots + i;
> + s = mt->slots + *p;
> + x = input_mt_get_value(s, ABS_MT_POSITION_X);
> + y = input_mt_get_value(s, ABS_MT_POSITION_Y);
> + dx = x - mt_pos->x;
> + dy = y - mt_pos->y;
> + d2 = dx * dx + dy * dy;
> + if (d2 >= mt->dmax2)
> + *p = -1;
> + }
> +}
> +
> +/**
> * input_mt_set_slots() - assign slots to the list of pos thanks to the reduced
> * cost matrix
> * @mt: the input_mt handle of the current device
> + * @pos: the position array to match
> * @slots: the slot assignment to be filled
> * @num_pos: number of positions
> *
> @@ -414,7 +456,8 @@ static int input_mt_set_matrix(struct input_mt *mt,
> * sent slots.
> */
> static void input_mt_set_slots(struct input_mt *mt,
> - int *slots, int num_pos)
> + const struct input_mt_pos *pos, int *slots,
> + int num_pos)
> {
> struct input_mt_slot *s;
> int *red_cost_matrix = mt->red;
> @@ -436,6 +479,8 @@ static void input_mt_set_slots(struct input_mt *mt,
> *p = s - mt->slots;
> }
>
> + input_mt_check_slots(mt, pos, slots, num_pos);
> +
> /* for each unassigned touch in pos, assign a new slot for it */
> for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
> if (input_mt_is_active(s))
> @@ -478,13 +523,31 @@ int input_mt_assign_slots(struct input_dev *dev, int *slots,
> n_rows = n_elems / num_pos;
> n_columns = num_pos;
> find_reduced_matrix(mt->red, n_columns, n_rows, n_elems);
> - input_mt_set_slots(mt, slots, num_pos);
> + input_mt_set_slots(mt, pos, slots, num_pos);
>
> return 0;
> }
> EXPORT_SYMBOL(input_mt_assign_slots);
>
> /**
> + * input_mt_set_dmax_tracking() - enhance tracking
> + * @dev: input device with allocated MT slots
> + * @dmax: the max distance between two touches to be considered as the same
> + *
> + * Enhance the in-kernel tracking by providing a maximum distance between
> + * 2 touches to be considered as the same slot.
> + * The stored value is the square of the provided distance to ease the tests
> + * later on. The input distance has to be given in the device coordinate system.
> + */
> +void input_mt_set_dmax_tracking(struct input_dev *dev, int dmax)
> +{
> + struct input_mt *mt = dev->mt;
> +
> + mt->dmax2 = dmax * dmax;
> +}
> +EXPORT_SYMBOL(input_mt_set_dmax_tracking);
> +
> +/**
> * input_mt_get_slot_by_key() - return slot matching key
> * @dev: input device with allocated MT slots
> * @key: the key of the sought slot
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index f89de89..95c15451 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -1077,7 +1077,8 @@ static void set_input_params(struct psmouse *psmouse,
> ABS_MT_POSITION_Y);
> /* Image sensors can report per-contact pressure */
> input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
> - input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK);
> + input_mt_init_slots(dev, 4, INPUT_MT_POINTER | INPUT_MT_TRACK);
> + input_mt_set_dmax_tracking(dev, 10 * priv->x_res);
>
> /* Image sensors can signal 4 and 5 finger clicks */
> __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
> diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h
> index f583ff6..c4b35c4 100644
> --- a/include/linux/input/mt.h
> +++ b/include/linux/input/mt.h
> @@ -41,6 +41,7 @@ struct input_mt_slot {
> * @flags: input_mt operation flags
> * @frame: increases every time input_mt_sync_frame() is called
> * @red: reduced cost matrix for in-kernel tracking
> + * @dmax2: max (squared) distance between 2 points when using in-kernel tracking
> * @slots: array of slots holding current values of tracked contacts
> */
> struct input_mt {
> @@ -50,6 +51,7 @@ struct input_mt {
> unsigned int flags;
> unsigned int frame;
> int *red;
> + int dmax2;
> struct input_mt_slot slots[];
> };
>
> @@ -100,6 +102,8 @@ static inline bool input_is_mt_axis(int axis)
> return axis == ABS_MT_SLOT || input_is_mt_value(axis);
> }
>
> +void input_mt_set_dmax_tracking(struct input_dev *dev, int dmax);
> +
> void input_mt_report_slot_state(struct input_dev *dev,
> unsigned int tool_type, bool active);
>
> --
> 2.1.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-01-19 21:03 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-19 20:53 [RFC 0/6] Input: mt: Document in-kernel tracking and solve jumping cursors issues Benjamin Tissoires
2015-01-19 20:53 ` [RFC 1/6] Input: mt: make input_mt_assign_slots() a little bit more readable Benjamin Tissoires
2015-01-19 20:53 ` [RFC 2/6] Input: mt: Document input_mt_set_slots() Benjamin Tissoires
2015-01-19 20:53 ` [RFC 3/6] Input: mt: document input_mt_set_matrix() Benjamin Tissoires
2015-01-19 20:53 ` [RFC 4/6] Input: mt: document find_reduced_matrix() Benjamin Tissoires
2015-01-19 20:53 ` [RFC 5/6] Input: mt: document adjust_dual() Benjamin Tissoires
2015-01-19 20:53 ` [RFC 6/6] Input: mt: introduce dmax in in-kernel tracking Benjamin Tissoires
2015-01-19 21:03 ` Benjamin Tissoires
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).