Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

256 lines (240 sloc) 6.25 kB
--- cyttsp_original/cyttsp_core.c 2011-08-16 02:42:06.000000000 +0200
+++ cyttsp/cyttsp_core.c 2011-08-16 02:34:33.000000000 +0200
@@ -7,6 +7,9 @@
* CY8CTMA340
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
+ * Copyright (C) 2011 Javier Martinez Canillas <martinez.javier@gmail.com>
+ *
+ * Added multi-touch protocol type B support by Javier Martinez Canillas
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -30,6 +33,7 @@
#include <linux/delay.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -64,22 +68,32 @@
#define CY_DEEP_SLEEP_MODE 0x02
#define CY_LOW_POWER_MODE 0x04
+/* Slots management */
+#define CY_MAX_FINGER 4
+#define CY_SLOT_UNUSED 0
+
struct cyttsp_tch {
__be16 x, y;
- u8 z, unused;
-} __attribute__((packed));
+ u8 z;
+} __packed;
/* TrueTouch Standard Product Gen3 interface definition */
struct cyttsp_xydata {
u8 hst_mode;
u8 tt_mode;
u8 tt_stat;
- struct cyttsp_tch tch[2];
- u8 unused_grp[12];
+ struct cyttsp_tch tch1;
+ u8 touch12_id;
+ struct cyttsp_tch tch2;
+ u8 gest_cnt;
+ u8 gest_id;
+ struct cyttsp_tch tch3;
+ u8 touch34_id;
+ struct cyttsp_tch tch4;
u8 tt_undef[3];
u8 act_dist;
u8 tt_reserved;
-} __attribute__((packed));
+} __packed;
/* TTSP System Information interface definition */
struct cyttsp_sysinfo_data {
@@ -137,6 +151,9 @@
struct cyttsp_sysinfo_data sysinfo_data;
struct completion bl_ready;
enum cyttsp_powerstate power_state;
+ int slot_cnt;
+ int slots[CY_MAX_FINGER];
+ int slot_status[CY_MAX_FINGER];
};
static const u8 bl_command[] = {
@@ -419,11 +436,83 @@
return retval;
}
+static void cyttsp_report_slot(struct input_dev *dev, int slot,
+ int x, int y, int z)
+{
+ input_mt_slot(dev, slot);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+ input_report_abs(dev, ABS_MT_POSITION_X, x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z);
+}
+
+static void cyttsp_report_slot_empty(struct input_dev *dev, int slot)
+{
+ input_mt_slot(dev, slot);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, false);
+}
+
+static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
+{
+ ids[0] = xy_data->touch12_id >> 4;
+ ids[1] = xy_data->touch12_id & 0xF;
+ ids[2] = xy_data->touch34_id >> 4;
+ ids[3] = xy_data->touch34_id & 0xF;
+}
+
+static void cyttsp_get_tch(struct cyttsp_xydata *xy_data, int idx,
+ struct cyttsp_tch **tch)
+{
+ switch (idx) {
+ case 0:
+ *tch = &xy_data->tch1;
+ break;
+ case 1:
+ *tch = &xy_data->tch2;
+ break;
+ case 2:
+ *tch = &xy_data->tch3;
+ break;
+ case 3:
+ *tch = &xy_data->tch4;
+ break;
+ }
+}
+
+static int cyttsp_get_slot_id(struct cyttsp *ts, int id)
+{
+ int i;
+
+ for (i = 0; i < CY_MAX_FINGER; i++)
+ if (ts->slots[i] == id)
+ return i;
+
+ return -1;
+}
+
+static int cyttsp_assign_next_slot(struct cyttsp *ts, int id)
+{
+ int i;
+
+ for (i = 0; i < CY_MAX_FINGER; i++)
+ if (ts->slots[i] == CY_SLOT_UNUSED) {
+ ts->slots[i] = id;
+ ts->slot_cnt++;
+ return i;
+ }
+
+ return -1;
+}
+
static int cyttsp_xy_worker(struct cyttsp *ts)
{
struct cyttsp_xydata xy_data;
u8 num_cur_tch;
int i;
+ int ids[4];
+ int slot = -1;
+ struct cyttsp_tch *tch = NULL;
+ int x, y, z;
/* Get touch data from CYTTSP device */
if (ttsp_read_block_data(ts,
@@ -451,7 +540,7 @@
/* terminate all active tracks */
num_cur_tch = 0;
dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
- } else if (num_cur_tch > 2) {
+ } else if (num_cur_tch > CY_MAX_FINGER) {
/* terminate all active tracks */
num_cur_tch = 0;
dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
@@ -461,20 +550,36 @@
dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
}
+ cyttsp_extract_track_ids(&xy_data, ids);
+
+ for (i = 0; i < CY_MAX_FINGER; i++)
+ ts->slot_status[i] = false;
+
for (i = 0; i < num_cur_tch; i++) {
- struct cyttsp_tch *tch = &xy_data.tch[i];
- int x = be16_to_cpu(tch->x);
- int y = be16_to_cpu(tch->y);
- int z = tch->z;
-
- input_report_abs(ts->input, ABS_MT_POSITION_X, x);
- input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, z);
- input_mt_sync(ts->input);
+ slot = cyttsp_get_slot_id(ts, ids[i]);
+
+ if (slot < 0)
+ slot = cyttsp_assign_next_slot(ts, ids[i]);
+
+ cyttsp_get_tch(&xy_data, i, &tch);
+
+ x = be16_to_cpu(tch->x);
+ y = be16_to_cpu(tch->y);
+ z = tch->z;
+
+ cyttsp_report_slot(ts->input, slot, x, y, z);
+
+ ts->slot_status[slot] = true;
}
- if (!num_cur_tch)
- input_mt_sync(ts->input);
+ for (i = 0; i < CY_MAX_FINGER; i++)
+ if (ts->slot_status[i] == false &&
+ ts->slots[i] != CY_SLOT_UNUSED) {
+ ts->slots[i] = CY_SLOT_UNUSED;
+ ts->slot_cnt--;
+ cyttsp_report_slot_empty(ts->input, i);
+ }
+
input_sync(ts->input);
return 0;
@@ -521,6 +626,7 @@
cyttsp_pr_state(ts);
}
}
+
return IRQ_HANDLED;
}
@@ -655,6 +761,7 @@
input_unregister_device(ts->input);
if (ts->platform_data->exit)
ts->platform_data->exit();
+ input_mt_destroy_slots(ts->input);
kfree(ts);
}
}
@@ -670,6 +777,7 @@
void *cyttsp_core_init(struct cyttsp_bus_ops *bus_ops, struct device *dev)
{
struct input_dev *input_device;
+ int i;
struct cyttsp *ts = kzalloc(sizeof(*ts), GFP_KERNEL);
@@ -726,11 +834,18 @@
__set_bit(EV_ABS, input_device->evbit);
input_set_abs_params(input_device, ABS_MT_POSITION_X,
- 0, ts->platform_data->maxx, 0, 0);
+ 0, ts->platform_data->maxx, 0, 0);
input_set_abs_params(input_device, ABS_MT_POSITION_Y,
- 0, ts->platform_data->maxy, 0, 0);
+ 0, ts->platform_data->maxy, 0, 0);
input_set_abs_params(input_device, ABS_MT_TOUCH_MAJOR,
- 0, CY_MAXZ, 0, 0);
+ 0, CY_MAXZ, 0, 0);
+
+ input_mt_init_slots(input_device, CY_MAX_FINGER);
+
+ for (i = 0; i < CY_MAX_FINGER; i++)
+ ts->slots[i] = CY_SLOT_UNUSED;
+
+ ts->slot_cnt = 0;
if (input_register_device(input_device)) {
dev_dbg(ts->dev, "%s: Error, failed to register input device\n",
Jump to Line
Something went wrong with that request. Please try again.