[PATCH] different modes to calculate the position.

From: Florian Loitsch
Date: Fri May 04 2007 - 19:41:51 EST


---
drivers/usb/input/appletouch.c | 123 +++++++++++++++++++++++++--------------
1 files changed, 79 insertions(+), 44 deletions(-)

diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 7ffe8e7..863ac08 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -136,6 +136,11 @@ MODULE_DEVICE_TABLE (usb, atp_table);
#define ATP_GEYSER3_MODE_REQUEST_INDEX 0
#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04

+#define ATP_MEAN_POS 0
+#define ATP_FIRST_FINGER_POS 1
+#define ATP_MEAN_FINGER_POS 2
+#define ATP_LAST_FINGER_POS 3
+
/* Structure to hold all of our device specific stuff */
struct atp {
char phys[64];
@@ -183,6 +188,13 @@ static int threshold = ATP_THRESHOLD;
module_param(threshold, int, 0644);
MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor
(trackpad has hundreds of these sensors) less than this value");

+static int x_position_mode = ATP_MEAN_POS;
+module_param(x_position_mode, int, 0644);
+MODULE_PARM_DESC(x_position_mode, "0 == mean, 1 == left-most finger, 2 ==
mean of all fingers, 3 == right-most finger");
+static int y_position_mode = ATP_MEAN_POS;
+module_param(y_position_mode, int, 0644);
+MODULE_PARM_DESC(y_position_mode, "0 == mean, 1 == top finger, 2 == mean of
all fingers, 3 == bottom finger");
+
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
@@ -209,62 +221,85 @@ static inline int atp_is_geyser_3(struct atp *dev)
(productId == GEYSER4_JIS_PRODUCT_ID);
}

+/*
+ * depending on the mode either:
+ * - calculates the mean position of all active sensors (ATP_MEAN_POS)
+ * - or calculates the position of each finger and returns
+ * * the position of the first found finger (ATP_FIRST_FINGER_POS)
+ * * the mean position of all found fingers (ATP_MEAN_FINGER_POS)
+ * * the position of the last found finger (ATP_LAST_FINGER_POS)
+ */
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
- int *z, int *fingers)
+ int mode, int *z, int *fingers)
{
int i;
/* values to calculate mean */
- int pcum = 0, psum = 0;
- int is_increasing = 0;
+ int finger_pcum, finger_psum;
+
+ int finger_pos;
+ int res_pos = 0; /* used as tmp-accumulator too */
+ int first_finger = 1;

*fingers = 0;

- for (i = 0; i < nb_sensors; i++) {
- if (xy_sensors[i] < threshold) {
- if (is_increasing)
- is_increasing = 0;
+ i = 0;
+ *z = 0;
+ /*
+ * As introduced by Jason Parekh still searches for humps on the sensors
+ * (transitions from nonincreasing to increasing) instead of transitions
+ * from low sensors (no finger reading) to high sensors (finger above
+ * sensor) to detect fingers.
+ */
+ do {
+ /* search first/next finger */
+ while (i < nb_sensors && xy_sensors[i] <= threshold) i++;
+ if (i >= nb_sensors)
+ break;

- continue;
+ /* found finger */
+ finger_pcum = (xy_sensors[i] - threshold) * i;
+ finger_psum = (xy_sensors[i] - threshold);
+ i++;
+ /* continue while increasing */
+ while (i < nb_sensors && xy_sensors[i-1] <= xy_sensors[i]) {
+ finger_pcum += (xy_sensors[i] - threshold) * i;
+ finger_psum += (xy_sensors[i] - threshold);
+ i++;
}

- /*
- * Makes the finger detection more versatile. For example,
- * two fingers with no gap will be detected. Also, my
- * tests show it less likely to have intermittent loss
- * of multiple finger readings while moving around (scrolling).
- *
- * Changes the multiple finger detection to counting humps on
- * sensors (transitions from nonincreasing to increasing)
- * instead of counting transitions from low sensors (no
- * finger reading) to high sensors (finger above
- * sensor)
- *
- * - Jason Parekh <jasonparekh@xxxxxxxxx>
- */
- if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
- (*fingers)++;
- is_increasing = 1;
- } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
- is_increasing = 0;
+ /* continue while decreasing (and staying above threshold) */
+ while (i < nb_sensors &&
+ xy_sensors[i] > threshold &&
+ xy_sensors[i-1] >= xy_sensors[i])
+ {
+ finger_pcum += (xy_sensors[i] - threshold) * i;
+ finger_psum += (xy_sensors[i] - threshold);
+ i++;
}

- /*
- * Subtracts threshold so a high sensor that just passes the threshold
- * won't skew the calculated absolute coordinate. Fixes an issue
- * where slowly moving the mouse would occassionaly jump a number of
- * pixels (let me restate--slowly moving the mouse makes this issue
- * most apparent).
- */
- pcum += (xy_sensors[i] - threshold) * i;
- psum += (xy_sensors[i] - threshold);
- }
+ if (mode == ATP_MEAN_POS)
+ res_pos += finger_pcum;
+ else {
+ finger_pos = finger_pcum * fact / finger_psum;
+ if ((first_finger && mode == ATP_FIRST_FINGER_POS) ||
+ mode == ATP_LAST_FINGER_POS)
+ res_pos = finger_pos;
+ else if (mode == ATP_MEAN_FINGER_POS)
+ res_pos += finger_pos;
+ }

- if (psum > 0) {
- *z = psum;
- return pcum * fact / psum;
- }
+ (*fingers)++;
+ *z += finger_psum;

- return 0;
+ first_finger = 0;
+ } while (i < nb_sensors);
+
+ if (mode == ATP_MEAN_POS && *fingers > 0)
+ res_pos = res_pos * fact / *z;
+ else if (mode == ATP_MEAN_FINGER_POS && *fingers > 0)
+ res_pos /= *fingers;
+
+ return res_pos;
}

static inline void atp_report_fingers(struct input_dev *input, int fingers)
@@ -415,9 +450,9 @@ static void atp_complete(struct urb* urb)
dbg_dump("accumulator", dev->xy_acc);

x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
- ATP_XFACT, &x_z, &x_f);
+ ATP_XFACT, x_position_mode, &x_z, &x_f);
y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
- ATP_YFACT, &y_z, &y_f);
+ ATP_YFACT, y_position_mode, &y_z, &y_f);

fingers = max(x_f, y_f);
if (x && y) {
--
1.5.1

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/