Input: bcm5974 - report ABS_MT events
authorHenrik Rydberg <rydberg@euromail.se>
Wed, 6 Jan 2010 08:32:48 +0000 (00:32 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 6 Jan 2010 08:33:46 +0000 (00:33 -0800)
Make bcm5974 report raw multi-touch (MT) data in the form of ABS_MT events.

[dtor@mail.ru: get rid of module option, always report all events]
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/mouse/bcm5974.c

index 0d1d33468b437182559e5163ca668abbc8780036..4f8fe0886b2a0470943eeb94625d375dd452cd1e 100644 (file)
@@ -139,6 +139,7 @@ struct tp_finger {
 /* trackpad finger data size, empirically at least ten fingers */
 #define SIZEOF_FINGER          sizeof(struct tp_finger)
 #define SIZEOF_ALL_FINGERS     (16 * SIZEOF_FINGER)
+#define MAX_FINGER_ORIENTATION 16384
 
 /* device-specific parameters */
 struct bcm5974_param {
@@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev,
        input_set_abs_params(input_dev, ABS_Y,
                                0, cfg->y.dim, cfg->y.fuzz, 0);
 
+       /* finger touch area */
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+                            cfg->w.devmin, cfg->w.devmax, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+                            cfg->w.devmin, cfg->w.devmax, 0, 0);
+       /* finger approach area */
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR,
+                            cfg->w.devmin, cfg->w.devmax, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR,
+                            cfg->w.devmin, cfg->w.devmax, 0, 0);
+       /* finger orientation */
+       input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
+                            -MAX_FINGER_ORIENTATION,
+                            MAX_FINGER_ORIENTATION, 0, 0);
+       /* finger position */
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                            cfg->x.devmin, cfg->x.devmax, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                            cfg->y.devmin, cfg->y.devmax, 0, 0);
+
        __set_bit(EV_KEY, input_dev->evbit);
        __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
@@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size)
        return 0;
 }
 
+static void report_finger_data(struct input_dev *input,
+                              const struct bcm5974_config *cfg,
+                              const struct tp_finger *f)
+{
+       input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major));
+       input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor));
+       input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major));
+       input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor));
+       input_report_abs(input, ABS_MT_ORIENTATION,
+                        MAX_FINGER_ORIENTATION - raw2int(f->orientation));
+       input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
+       input_report_abs(input, ABS_MT_POSITION_Y,
+                        cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y));
+       input_mt_sync(input);
+}
+
 /* report trackpad data as logical trackpad state */
 static int report_tp_state(struct bcm5974 *dev, int size)
 {
        const struct bcm5974_config *c = &dev->cfg;
        const struct tp_finger *f;
        struct input_dev *input = dev->input;
-       int raw_p, raw_w, raw_x, raw_y, raw_n;
+       int raw_p, raw_w, raw_x, raw_y, raw_n, i;
        int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
        int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
 
@@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 
        /* always track the first finger; when detached, start over */
        if (raw_n) {
+
+               /* report raw trackpad data */
+               for (i = 0; i < raw_n; i++)
+                       report_finger_data(input, c, &f[i]);
+
                raw_p = raw2int(f->force_major);
                raw_w = raw2int(f->size_major);
                raw_x = raw2int(f->abs_x);