This patch optionally provides a mode of multitouch that works with
Qt 4.7's approach of taking input from multiple /dev/input/event
interfaces. It does so by creating one input device for each supported
contact point (2 in this case)
If there is another way to create mulitiple event interfaces on
a single input device, please point me to them.
Once the new multi-touch protocol is supported up the entire vertical
stack, I expect this would shift to support that mechanism of exposing
multitouch data.
The above is enabled via CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
with the default set to 'Y' (to enable current Qt 4.7 based applications
to leverage this capability)
Signed-off-by: James Ketrenos <jketr...@linux.intel.com>
---
drivers/input/touchscreen/Kconfig | 13 +++++
drivers/input/touchscreen/cy8ctmg110_ts.c | 76
+++++++++++++++++++++++++++--
2 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/Kconfig
b/drivers/input/touchscreen/Kconfig
index 6f08b10..a103384 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -615,6 +615,19 @@ config TOUCHSCREEN_CY8CTMG110
To compile this driver as a module, choose M here: the
module will be called cy8ctmg110_ts.
+config TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ bool "cy8ctmg110 multiple interface support"
+ default y
+ depends on TOUCHSCREEN_CY8CTMG110
+ help
+ Say Y here if you want each contact point (up to 2) supported by
+ the cy8ctmg110 capacitive touchscreen to be exposed as a
+ seperate input device.
+
+ This enables MPX and some multi-touch applications to work.
+
+ If unsure, say Y.
+
config TOUCHSCREEN_CLEARPAD_TM1217
tristate "Synaptics Clearpad TM1217"
depends on I2C
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c
b/drivers/input/touchscreen/cy8ctmg110_ts.c
index e8c499a..9221d80 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -81,8 +81,13 @@ struct ts_event {
* The touch driver structure.
*/
struct cy8ctmg110 {
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ struct input_dev *input[MAX_FINGERS];
+ char phys[MAX_FINGERS][32];
+#else
struct input_dev *input;
char phys[32];
+#endif
struct ts_event tc;
struct i2c_client *client;
spinlock_t lock;
@@ -203,6 +208,30 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
if (tsc->tc.fingers > MAX_FINGERS)
tsc->tc.fingers = 0;
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ /*
+ * Set/Clear BTN_TOUCH bit based on if there is an active contact
+ * point on that input device.
+ */
+ input_event(tsc->input[0], EV_KEY, BTN_TOUCH, tsc->tc.fingers > 0);
+ input_event(tsc->input[1], EV_KEY, BTN_TOUCH, tsc->tc.fingers > 1);
+
+ /*
+ * Track the '1st' finger; this might need to be improved as it
+ * could result in a borken experience when the user presses
+ * with contact 1, presses contact 2, then releases contact 1.
+ */
+ if (tsc->tc.fingers > 0) {
+ input_report_abs(tsc->input[0], ABS_X, tsc->tc.x1);
+ input_report_abs(tsc->input[0], ABS_Y, tsc->tc.y1);
+ }
+ input_sync(tsc->input[0]);
+ if (tsc->tc.fingers > 1) {
+ input_report_abs(tsc->input[1], ABS_X, tsc->tc.x2);
+ input_report_abs(tsc->input[1], ABS_Y, tsc->tc.y2);
+ }
+ input_sync(tsc->input[1]);
+#else
/* Set/Clear BTN_TOUCH bit based on if any contact points */
input_event(tsc->input, EV_KEY, BTN_TOUCH, tsc->tc.fingers);
@@ -216,7 +245,7 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
input_report_abs(tsc->input, ABS_Y, tsc->tc.y1);
}
input_sync(tsc->input);
-
+#endif
return 0;
}
@@ -272,6 +301,9 @@ static int cy8ctmg110_probe(struct i2c_client *client,
{
struct cy8ctmg110 *ts;
struct input_dev *input_dev;
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ int contact;
+#endif
int err;
if (!i2c_check_functionality(client->adapter,
@@ -372,7 +404,29 @@ failed_irq:
if (ts->polling)
hrtimer_start(&ts->timer, ktime_set(10, 0), HRTIMER_MODE_REL);
- err = input_register_device(input_dev);
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ for (contact = 0; contact < MAX_FINGERS; contact++) {
+ err = input_register_device(ts->input[contact]);
+ if (err) {
+ /*
+ * For the input devices that have successfully
+ * registered before this failure, call
+ * input_unregister_device() and clear the input[]
+ * value so the err_free_mem code path doesn't call
+ * input_free_device on it
+ */
+ while (contact) {
+ input_unregister_device(ts->input[contact]);
+ ts->input[contact] = NULL;
+ contact--;
+ }
+ break;
+ }
+ }
+#else
+ err = input_register_device(ts->input);
+#endif
+
if (!err)
return 0;
@@ -383,7 +437,14 @@ failed_irq:
gpio_free(CY8CTMG110_IRQ_PIN_GPIO);
gpio_free(CY8CTMG110_RESET_PIN_GPIO);
err_free_mem:
- input_free_device(input_dev);
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ for (contact = 0; contact < MAX_FINGERS; contact++) {
+ if (ts->input[contact])
+ input_free_device(ts->input[contact]);
+ }
+#else
+ input_free_device(ts->input);
+#endif
kfree(ts);
return err;
}
@@ -437,13 +498,20 @@ static int cy8ctmg110_resume(struct i2c_client
*client)
static int cy8ctmg110_remove(struct i2c_client *client)
{
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
-
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ int contact;
+#endif
cy8ctmg110_power(0);
if (ts->polling)
hrtimer_cancel(&ts->timer);
free_irq(client->irq, ts);
+#ifdef CONFIG_TOUCHSCREEN_CY8CTMG110_MULTIPLE_INPUT
+ for (contact = 0; contact < MAX_FINGERS; contact++)
+ input_unregister_device(ts->input[contact]);
+#else
input_unregister_device(ts->input);
+#endif
gpio_free(CY8CTMG110_IRQ_PIN_GPIO);
gpio_free(CY8CTMG110_RESET_PIN_GPIO);
kfree(ts);
--
1.7.1
_______________________________________________
MeeGo-dev mailing list
MeeGo-dev@meego.com
http://lists.meego.com/listinfo/meego-dev