generic-poky/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-multi-touch-in...

399 lines
9.9 KiB
Diff

From 6317c631cb1fd32f34da98a945747781d5a8906d Mon Sep 17 00:00:00 2001
From: Priya Vijayan <priya.vijayan@intel.com>
Date: Tue, 4 May 2010 14:21:37 -0700
Subject: [PATCH] Add mtdev driver and configs
Add multi-touch driver and configs for event devices.
This module is from He Min <min.he@intel.com>
Code modifications and configs from Priya Vijayan <priya.vijayan@intel.com>
Patch-mainline: 2.6.34
Signed-off-by: Priya Vijayan <priya.vijayan@intel.com>
---
drivers/input/Kconfig | 9 ++
drivers/input/Makefile | 1 +
drivers/input/input.c | 1 +
drivers/input/mtdev.c | 307 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/input.h | 1 +
5 files changed, 319 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/mtdev.c
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 07c2cd4..0264508 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -135,6 +135,15 @@ config INPUT_EVDEV
To compile this driver as a module, choose M here: the
module will be called evdev.
+config INPUT_MTDEV
+ tristate "Multitouch interface"
+ help
+ Say Y here if you want to enable Multi-touch input driver for event devices
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here:the
+ module will be called mtdev.
+
config INPUT_EVBUG
tristate "Event debugging"
help
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 7ad212d..96a4d94 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
obj-$(CONFIG_INPUT_EVDEV) += evdev.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o
+obj-$(CONFIG_INPUT_MTDEV) += mtdev.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
obj-$(CONFIG_INPUT_MOUSE) += mouse/
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 86cb2d2..b589dec 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -47,6 +47,7 @@ static unsigned int input_abs_bypass_init_data[] __initdata = {
ABS_MT_BLOB_ID,
ABS_MT_TRACKING_ID,
ABS_MT_PRESSURE,
+ ABS_MT_CONTACT_COUNT,
0
};
static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
diff --git a/drivers/input/mtdev.c b/drivers/input/mtdev.c
new file mode 100644
index 0000000..8b01220
--- /dev/null
+++ b/drivers/input/mtdev.c
@@ -0,0 +1,312 @@
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
+
+#define MTDEV_MAX_POINTERS 5
+
+#ifndef ABS_MT_PRESSURE
+#define ABS_MT_PRESSURE 0x3a
+#endif
+#ifndef ABS_MT_CONTACT_COUNT
+#define ABS_MT_CONTACT_COUNT 0x3b
+#endif
+
+struct mtdev_input_dev
+{
+ struct input_dev* input_dev;
+ int id;
+ bool ready;
+ int x;
+ int y;
+ int z;
+ int touch;
+};
+
+struct mtdev_dev
+{
+ int count;
+ int last_count;
+ wait_queue_head_t wq;
+ struct input_handle handle;
+ struct mtdev_input_dev devs[MTDEV_MAX_POINTERS];
+};
+
+//id==-1 means to find an empty slot
+static int find_match_id(struct mtdev_dev * mtdev,int id)
+{
+ int i=0;
+
+ for (i=0;i<MTDEV_MAX_POINTERS;i++)
+ {
+ if(mtdev->devs[i].id==id)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+static int mtdev_kt(void *data)
+{
+ struct mtdev_dev *mtdev=(struct mtdev_dev*)data;
+ int i=0;
+ int err=0;
+ printk("mtdev_kt entered\n");
+ if(!mtdev)
+ return -1;
+ //wait_event_interruptible(mtdev->wq,kthread_should_stop());
+ for(;i<MTDEV_MAX_POINTERS;i++)
+ {
+ struct input_dev *pdev=NULL;
+ pdev=mtdev->devs[i].input_dev;
+
+ err=input_register_device(pdev);
+ if(err)
+ {
+ printk("error in register mtdev %d\n",err);
+ return err;
+ }
+ else
+ printk("successfully registered input %d\n",i);
+ mtdev->devs[i].ready=true;
+
+ }
+ return 0;
+}
+
+static void mtdev_event(struct input_handle * handle,
+ unsigned int type, unsigned int code, int value)
+{
+ static int i=0;
+ //int err=0;
+ int j=0;
+ struct mtdev_dev *mtdev=handle->private;
+ //printk("mtdev_event %x %x %x\n",type,code,value);
+ if(!mtdev->devs[1].ready||!mtdev->devs[0].ready)
+ return;
+ if(type==EV_ABS)
+ {
+ switch(code)
+ {
+ case ABS_MT_CONTACT_COUNT:
+ if(value!=0)
+ {
+ //we start from the first point
+ i=0;
+ //printk("mtdev:contact count is %d\n",value);
+ }
+ else if(value>MTDEV_MAX_POINTERS)
+ {
+ value=MTDEV_MAX_POINTERS;
+ }
+
+ //found last release fingers and send release event
+ for(j=0;j<MTDEV_MAX_POINTERS;j++)
+ {
+ if(mtdev->devs[j].touch==0
+ &&mtdev->devs[j].id!=-1)
+ {
+ input_report_key(mtdev->devs[j].input_dev,BTN_TOUCH,0);
+ input_sync(mtdev->devs[j].input_dev);
+ printk("%d id %d released\n",j,mtdev->devs[j].id);
+ mtdev->devs[j].id=-1;
+ }
+ mtdev->devs[j].touch=0;
+ }
+ mtdev->count=value;
+
+ mtdev->last_count=value;
+
+ break;
+ case ABS_MT_TRACKING_ID:
+ {
+ i=find_match_id(mtdev,value);
+ if(i==-1||i>=MTDEV_MAX_POINTERS)
+ {
+ i=find_match_id(mtdev,-1);
+ if(i==-1||i>=MTDEV_MAX_POINTERS)
+ {
+ printk("no empty slot for id %d\n",value);
+ break;
+ }
+ else
+ {
+ //newly pressed
+ mtdev->devs[i].touch=2;
+ mtdev->devs[i].id=value;
+ printk("found slot %d for id %d\n",i,value);
+ break;
+ }
+ }
+ //printk("found slot %d for id%d\n",i,value);
+ //keep the point
+ mtdev->devs[i].touch=1;
+
+ }
+ break;
+ case ABS_MT_POSITION_X:
+ if(i<MTDEV_MAX_POINTERS&&i!=-1)
+ mtdev->devs[i].x=value;
+ //printk("mt x :%d\n",value);
+ break;
+ case ABS_MT_POSITION_Y:
+ if(i<MTDEV_MAX_POINTERS&&i!=-1)
+ mtdev->devs[i].y=value;
+ //printk("mt y :%d\n",value);
+ break;
+ case ABS_MT_PRESSURE:
+ if(i<MTDEV_MAX_POINTERS&&i!=-1)
+ mtdev->devs[i].z=value;
+ break;
+ default:
+ break;
+ }
+ }
+ else if(type == EV_SYN && code == SYN_MT_REPORT)
+ {
+ if(i<MTDEV_MAX_POINTERS&&i!=-1)
+ {
+ if(mtdev->devs[i].touch==2)
+ {
+ input_report_key(mtdev->devs[i].input_dev,BTN_TOUCH,1);
+
+ }
+ input_report_abs(mtdev->devs[i].input_dev,ABS_X,mtdev->devs[i].x);
+ input_report_abs(mtdev->devs[i].input_dev,ABS_Y,mtdev->devs[i].y);
+ input_report_abs(mtdev->devs[i].input_dev,ABS_PRESSURE,mtdev->devs[i].z);
+ input_sync(mtdev->devs[i].input_dev);
+ //printk("mtdev_event %d id %d (%d,%d,%d)\n",i,mtdev->devs[i].id,mtdev->devs[i].x,mtdev->devs[i].y,mtdev->devs[i].z);
+ //i++;
+ }
+ }
+
+}
+/*
+ * grab all the input of mt device, create new single touch input devices
+ *
+ */
+static int mtdev_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct mtdev_dev* mtdev;
+ struct task_struct * task=NULL;
+ int i=0;
+ int err=0;
+ printk("mtdev_connect\n");
+ mtdev=kzalloc(sizeof(struct mtdev_dev),GFP_KERNEL);
+ if(!mtdev)
+ return -ENOMEM;
+ mtdev->handle.dev=input_get_device(dev);
+ mtdev->handle.name="mtdev";
+ mtdev->handle.handler=handler;
+ mtdev->handle.private=mtdev;
+ mtdev->count=0;
+ mtdev->last_count=0;
+ init_waitqueue_head(&mtdev->wq);
+ for(;i<MTDEV_MAX_POINTERS;i++)
+ {
+ //we just store the data here, and will register it
+ //when the first event comes
+ struct input_dev *pdev=NULL;
+ mtdev->devs[i].ready=false;
+ mtdev->devs[i].id=-1;
+ mtdev->devs[i].touch=-1;
+ mtdev->devs[i].input_dev=input_allocate_device();
+ if(!mtdev->devs[i].input_dev)
+ return -ENOMEM;
+ pdev=mtdev->devs[i].input_dev;
+ memcpy(pdev->evbit,dev->evbit,sizeof(pdev->evbit));
+ memcpy(pdev->keybit,dev->keybit,sizeof(pdev->keybit));
+ memcpy(pdev->absbit,dev->absbit,sizeof(pdev->absbit));
+
+ memcpy(pdev->abs,dev->abs,sizeof(pdev->abs));
+ memcpy(pdev->absmax,dev->absmax,sizeof(pdev->absmax));
+ memcpy(pdev->absmin,dev->absmin,sizeof(pdev->absmin));
+
+ pdev->name="mtdev virtual input";
+ }
+
+ //create a thread to create the new input devices
+ //because there's a mutex,which may cause dead lock
+ task=kthread_run(mtdev_kt,mtdev,"mtdev thread");
+ if(!task)
+ printk("error !!!!\n");
+ else
+ printk("kthread created OK\n");
+
+
+ err=input_grab_device(&mtdev->handle);
+ if(err)
+ {
+ printk("error in grab device %d\n",err);
+ return err;
+ }
+ else
+ printk("successfully grab device \n");
+
+ wake_up_all(&mtdev->wq);
+ return 0;
+}
+
+static void mtdev_disconnect(struct input_handle *handle)
+{
+ printk("mtdev_disconnect\n");
+ input_release_device(handle);
+}
+
+static const struct input_device_id mtdev_ids[] = {
+ {
+ .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
+ .vendor=0x1f87,
+ .product=0x0002,
+ },
+ {
+ .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
+ .vendor=0x1f87,
+ .product=0x0001,
+ },
+ {
+ .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
+ .vendor=0x0483,
+ .product=0x3261,
+ },
+ {
+ .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
+ .vendor=0x2087,
+ .product=0x0a01,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(input,mtdev_ids);
+
+static struct input_handler mtdev_handler = {
+ .event = mtdev_event,
+ .connect = mtdev_connect,
+ .disconnect = mtdev_disconnect,
+ .name = "mtdev",
+ .id_table = mtdev_ids,
+};
+
+
+static int __init mtdev_init(void)
+{
+ return input_register_handler(&mtdev_handler);
+}
+
+static void __exit mtdev_exit(void)
+{
+ input_unregister_handler(&mtdev_handler);
+}
+
+module_init(mtdev_init);
+module_exit(mtdev_exit);
+
+MODULE_AUTHOR("He Min <min.he@intel.com>");
+MODULE_DESCRIPTION("Multi-touch input driver event devices");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/input.h b/include/linux/input.h
index 663208a..55bf8bc 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -662,6 +662,7 @@ struct input_absinfo {
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
+#define ABS_MT_CONTACT_COUNT 0x3b /* Contact count */
#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)
--
1.6.2.2