summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNitin Garg <nitin.garg@freescale.com>2012-06-07 14:15:14 -0500
committerNitin Garg <nitin.garg@freescale.com>2012-06-07 14:19:32 -0500
commitb339ccc94311954734decf3eb82c14a4ce561c03 (patch)
treecc549be9bef52d57eabe75619725d46288a560e8 /drivers
parente80836e63ee58d8cb31750cc11618de0e0f8f8fb (diff)
ENGR00176332: Fishing master Popup 'Unfortunately, Fishing master has stopped.'
This is a fix for the fishing master app stopping on a single touch event. The fishing master app has another issue that it dies on 2 touch events, which is an app implementation issue. Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/egalax_ts.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 4777fe5abbad..6bd7c5434432 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -70,23 +70,53 @@
#define EGALAX_MAX_Z 2048
#define EGALAX_MAX_TRIES 100
+struct finger_info {
+ s16 x;
+ s16 y;
+ s16 z;
+};
+
struct egalax_ts {
struct i2c_client *client;
struct input_dev *input_dev;
- int old_x;
- int old_y;
- int old_z;
- int old_id;
- int old_state;
#ifdef CONFIG_EARLYSUSPEND
struct early_suspend es_handler;
#endif
+ u32 finger_mask;
+ struct finger_info fingers[MAX_SUPPORT_POINTS];
};
+static void report_input_data(struct egalax_ts *data)
+{
+ int i;
+ int num_fingers_down;
+
+ num_fingers_down = 0;
+ for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
+ if (data->fingers[i].z == -1)
+ continue;
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ data->fingers[i].x);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ data->fingers[i].y);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ data->fingers[i].z);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, i);
+ input_mt_sync(data->input_dev);
+ num_fingers_down++;
+ }
+ data->finger_mask = 0;
+
+ if (num_fingers_down == 0)
+ input_mt_sync(data->input_dev);
+ input_sync(data->input_dev);
+}
+
static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
{
struct egalax_ts *data = dev_id;
- struct input_dev *input_dev = data->input_dev;
struct i2c_client *client = data->client;
u8 buf[MAX_I2C_DATA_LEN];
int id, ret, x, y, z;
@@ -117,41 +147,32 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET;
down = state & EVENT_DOWN_UP;
- if (x == data->old_x && y == data->old_y && z == data->old_z
- && id == data->old_id && down == data->old_state) {
- continue;
- } else {
- data->old_x = x;
- data->old_y = y;
- data->old_z = z;
- data->old_id = id;
- data->old_state = down;
- }
-
if (!valid || id >= MAX_SUPPORT_POINTS) {
dev_dbg(&client->dev, "point invalid\n");
return IRQ_HANDLED;
}
- input_mt_slot(input_dev, id);
- input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down);
-
- dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d\n",
- (down ? "down" : "up"), id, x, y, z);
+ if (data->finger_mask & (1U << id))
+ report_input_data(data);
- if (down) {
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_report_abs(input_dev, ABS_MT_PRESSURE, z);
+ if (!down) {
+ data->fingers[id].z = -1;
+ data->finger_mask |= 1U << id;
} else {
- input_report_abs(input_dev, ABS_MT_PRESSURE, 0);
+ data->fingers[id].x = x;
+ data->fingers[id].y = y;
+ data->fingers[id].z = z;
+ data->finger_mask |= 1U << id;
}
- input_report_key(input_dev, BTN_TOUCH, !!down);
- input_sync(input_dev);
+
+ dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d\n",
+ (down ? "down" : "up"), id, x, y, z);
} while (gpio_get_value(irq_to_gpio(client->irq)) == 0);
+ if (data->finger_mask)
+ report_input_data(data);
+
return IRQ_HANDLED;
}
@@ -237,13 +258,8 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
- __set_bit(EV_SYN, input_dev->evbit);
__set_bit(EV_ABS, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0);
input_set_abs_params(input_dev,
ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
input_set_abs_params(input_dev,
@@ -251,7 +267,8 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev,
ABS_MT_PRESSURE, 0, EGALAX_MAX_Z, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 1, 0, 0);
- input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS);
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+ MAX_SUPPORT_POINTS-1, 0, 0);
input_set_drvdata(input_dev, data);