From 6317c631cb1fd32f34da98a945747781d5a8906d Mon Sep 17 00:00:00 2001 From: Priya Vijayan 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 Code modifications and configs from Priya Vijayan Patch-mainline: 2.6.34 Signed-off-by: Priya Vijayan --- 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 +#include +#include +#include +#include +#include +#include + +#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;idevs[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(;idevs[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;jdevs[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(idevs[i].x=value; + //printk("mt x :%d\n",value); + break; + case ABS_MT_POSITION_Y: + if(idevs[i].y=value; + //printk("mt y :%d\n",value); + break; + case ABS_MT_PRESSURE: + if(idevs[i].z=value; + break; + default: + break; + } + } + else if(type == EV_SYN && code == SYN_MT_REPORT) + { + if(idevs[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(;idevs[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 "); +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