1 From 6317c631cb1fd32f34da98a945747781d5a8906d Mon Sep 17 00:00:00 2001
2 From: Priya Vijayan <priya.vijayan@intel.com>
3 Date: Tue, 4 May 2010 14:21:37 -0700
4 Subject: [PATCH] Add mtdev driver and configs
6 Add multi-touch driver and configs for event devices.
7 This module is from He Min <min.he@intel.com>
8 Code modifications and configs from Priya Vijayan <priya.vijayan@intel.com>
10 Patch-mainline: 2.6.34
12 Signed-off-by: Priya Vijayan <priya.vijayan@intel.com>
14 drivers/input/Kconfig | 9 ++
15 drivers/input/Makefile | 1 +
16 drivers/input/input.c | 1 +
17 drivers/input/mtdev.c | 307 ++++++++++++++++++++++++++++++++++++++++++++++++
18 include/linux/input.h | 1 +
19 5 files changed, 319 insertions(+), 0 deletions(-)
20 create mode 100644 drivers/input/mtdev.c
22 diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
23 index 07c2cd4..0264508 100644
24 --- a/drivers/input/Kconfig
25 +++ b/drivers/input/Kconfig
26 @@ -135,6 +135,15 @@ config INPUT_EVDEV
27 To compile this driver as a module, choose M here: the
28 module will be called evdev.
31 + tristate "Multitouch interface"
33 + Say Y here if you want to enable Multi-touch input driver for event devices
36 + To compile this driver as a module, choose M here:the
37 + module will be called mtdev.
40 tristate "Event debugging"
42 diff --git a/drivers/input/Makefile b/drivers/input/Makefile
43 index 7ad212d..96a4d94 100644
44 --- a/drivers/input/Makefile
45 +++ b/drivers/input/Makefile
46 @@ -15,6 +15,7 @@ obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
47 obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
48 obj-$(CONFIG_INPUT_EVDEV) += evdev.o
49 obj-$(CONFIG_INPUT_EVBUG) += evbug.o
50 +obj-$(CONFIG_INPUT_MTDEV) += mtdev.o
52 obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
53 obj-$(CONFIG_INPUT_MOUSE) += mouse/
54 diff --git a/drivers/input/input.c b/drivers/input/input.c
55 index 86cb2d2..b589dec 100644
56 --- a/drivers/input/input.c
57 +++ b/drivers/input/input.c
58 @@ -47,6 +47,7 @@ static unsigned int input_abs_bypass_init_data[] __initdata = {
62 + ABS_MT_CONTACT_COUNT,
65 static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
66 diff --git a/drivers/input/mtdev.c b/drivers/input/mtdev.c
68 index 0000000..8b01220
70 +++ b/drivers/input/mtdev.c
72 +#include <linux/module.h>
73 +#include <linux/input.h>
74 +#include <linux/init.h>
75 +#include <linux/device.h>
76 +#include <linux/hid.h>
77 +#include <linux/wait.h>
78 +#include <linux/kthread.h>
80 +#define MTDEV_MAX_POINTERS 5
82 +#ifndef ABS_MT_PRESSURE
83 +#define ABS_MT_PRESSURE 0x3a
85 +#ifndef ABS_MT_CONTACT_COUNT
86 +#define ABS_MT_CONTACT_COUNT 0x3b
89 +struct mtdev_input_dev
91 + struct input_dev* input_dev;
104 + wait_queue_head_t wq;
105 + struct input_handle handle;
106 + struct mtdev_input_dev devs[MTDEV_MAX_POINTERS];
109 +//id==-1 means to find an empty slot
110 +static int find_match_id(struct mtdev_dev * mtdev,int id)
114 + for (i=0;i<MTDEV_MAX_POINTERS;i++)
116 + if(mtdev->devs[i].id==id)
125 +static int mtdev_kt(void *data)
127 + struct mtdev_dev *mtdev=(struct mtdev_dev*)data;
130 + printk("mtdev_kt entered\n");
133 + //wait_event_interruptible(mtdev->wq,kthread_should_stop());
134 + for(;i<MTDEV_MAX_POINTERS;i++)
136 + struct input_dev *pdev=NULL;
137 + pdev=mtdev->devs[i].input_dev;
139 + err=input_register_device(pdev);
142 + printk("error in register mtdev %d\n",err);
146 + printk("successfully registered input %d\n",i);
147 + mtdev->devs[i].ready=true;
153 +static void mtdev_event(struct input_handle * handle,
154 + unsigned int type, unsigned int code, int value)
159 + struct mtdev_dev *mtdev=handle->private;
160 + //printk("mtdev_event %x %x %x\n",type,code,value);
161 + if(!mtdev->devs[1].ready||!mtdev->devs[0].ready)
167 + case ABS_MT_CONTACT_COUNT:
170 + //we start from the first point
172 + //printk("mtdev:contact count is %d\n",value);
174 + else if(value>MTDEV_MAX_POINTERS)
176 + value=MTDEV_MAX_POINTERS;
179 + //found last release fingers and send release event
180 + for(j=0;j<MTDEV_MAX_POINTERS;j++)
182 + if(mtdev->devs[j].touch==0
183 + &&mtdev->devs[j].id!=-1)
185 + input_report_key(mtdev->devs[j].input_dev,BTN_TOUCH,0);
186 + input_sync(mtdev->devs[j].input_dev);
187 + printk("%d id %d released\n",j,mtdev->devs[j].id);
188 + mtdev->devs[j].id=-1;
190 + mtdev->devs[j].touch=0;
192 + mtdev->count=value;
194 + mtdev->last_count=value;
197 + case ABS_MT_TRACKING_ID:
199 + i=find_match_id(mtdev,value);
200 + if(i==-1||i>=MTDEV_MAX_POINTERS)
202 + i=find_match_id(mtdev,-1);
203 + if(i==-1||i>=MTDEV_MAX_POINTERS)
205 + printk("no empty slot for id %d\n",value);
211 + mtdev->devs[i].touch=2;
212 + mtdev->devs[i].id=value;
213 + printk("found slot %d for id %d\n",i,value);
217 + //printk("found slot %d for id%d\n",i,value);
219 + mtdev->devs[i].touch=1;
223 + case ABS_MT_POSITION_X:
224 + if(i<MTDEV_MAX_POINTERS&&i!=-1)
225 + mtdev->devs[i].x=value;
226 + //printk("mt x :%d\n",value);
228 + case ABS_MT_POSITION_Y:
229 + if(i<MTDEV_MAX_POINTERS&&i!=-1)
230 + mtdev->devs[i].y=value;
231 + //printk("mt y :%d\n",value);
233 + case ABS_MT_PRESSURE:
234 + if(i<MTDEV_MAX_POINTERS&&i!=-1)
235 + mtdev->devs[i].z=value;
241 + else if(type == EV_SYN && code == SYN_MT_REPORT)
243 + if(i<MTDEV_MAX_POINTERS&&i!=-1)
245 + if(mtdev->devs[i].touch==2)
247 + input_report_key(mtdev->devs[i].input_dev,BTN_TOUCH,1);
250 + input_report_abs(mtdev->devs[i].input_dev,ABS_X,mtdev->devs[i].x);
251 + input_report_abs(mtdev->devs[i].input_dev,ABS_Y,mtdev->devs[i].y);
252 + input_report_abs(mtdev->devs[i].input_dev,ABS_PRESSURE,mtdev->devs[i].z);
253 + input_sync(mtdev->devs[i].input_dev);
254 + //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);
261 + * grab all the input of mt device, create new single touch input devices
264 +static int mtdev_connect(struct input_handler *handler, struct input_dev *dev,
265 + const struct input_device_id *id)
267 + struct mtdev_dev* mtdev;
268 + struct task_struct * task=NULL;
271 + printk("mtdev_connect\n");
272 + mtdev=kzalloc(sizeof(struct mtdev_dev),GFP_KERNEL);
275 + mtdev->handle.dev=input_get_device(dev);
276 + mtdev->handle.name="mtdev";
277 + mtdev->handle.handler=handler;
278 + mtdev->handle.private=mtdev;
280 + mtdev->last_count=0;
281 + init_waitqueue_head(&mtdev->wq);
282 + for(;i<MTDEV_MAX_POINTERS;i++)
284 + //we just store the data here, and will register it
285 + //when the first event comes
286 + struct input_dev *pdev=NULL;
287 + mtdev->devs[i].ready=false;
288 + mtdev->devs[i].id=-1;
289 + mtdev->devs[i].touch=-1;
290 + mtdev->devs[i].input_dev=input_allocate_device();
291 + if(!mtdev->devs[i].input_dev)
293 + pdev=mtdev->devs[i].input_dev;
294 + memcpy(pdev->evbit,dev->evbit,sizeof(pdev->evbit));
295 + memcpy(pdev->keybit,dev->keybit,sizeof(pdev->keybit));
296 + memcpy(pdev->absbit,dev->absbit,sizeof(pdev->absbit));
298 + memcpy(pdev->abs,dev->abs,sizeof(pdev->abs));
299 + memcpy(pdev->absmax,dev->absmax,sizeof(pdev->absmax));
300 + memcpy(pdev->absmin,dev->absmin,sizeof(pdev->absmin));
302 + pdev->name="mtdev virtual input";
305 + //create a thread to create the new input devices
306 + //because there's a mutex,which may cause dead lock
307 + task=kthread_run(mtdev_kt,mtdev,"mtdev thread");
309 + printk("error !!!!\n");
311 + printk("kthread created OK\n");
314 + err=input_grab_device(&mtdev->handle);
317 + printk("error in grab device %d\n",err);
321 + printk("successfully grab device \n");
323 + wake_up_all(&mtdev->wq);
327 +static void mtdev_disconnect(struct input_handle *handle)
329 + printk("mtdev_disconnect\n");
330 + input_release_device(handle);
333 +static const struct input_device_id mtdev_ids[] = {
335 + .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
340 + .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
345 + .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
350 + .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
357 +MODULE_DEVICE_TABLE(input,mtdev_ids);
359 +static struct input_handler mtdev_handler = {
360 + .event = mtdev_event,
361 + .connect = mtdev_connect,
362 + .disconnect = mtdev_disconnect,
364 + .id_table = mtdev_ids,
368 +static int __init mtdev_init(void)
370 + return input_register_handler(&mtdev_handler);
373 +static void __exit mtdev_exit(void)
375 + input_unregister_handler(&mtdev_handler);
378 +module_init(mtdev_init);
379 +module_exit(mtdev_exit);
381 +MODULE_AUTHOR("He Min <min.he@intel.com>");
382 +MODULE_DESCRIPTION("Multi-touch input driver event devices");
383 +MODULE_LICENSE("GPL");
384 diff --git a/include/linux/input.h b/include/linux/input.h
385 index 663208a..55bf8bc 100644
386 --- a/include/linux/input.h
387 +++ b/include/linux/input.h
388 @@ -662,6 +662,7 @@ struct input_absinfo {
389 #define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
390 #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
391 #define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
392 +#define ABS_MT_CONTACT_COUNT 0x3b /* Contact count */
395 #define ABS_CNT (ABS_MAX+1)