]> code.ossystems Code Review - openembedded-core.git/blob
483862ae227a9f2d015ce30ca3369efbef68220a
[openembedded-core.git] /
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
5
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>
9
10 Patch-mainline: 2.6.34
11
12 Signed-off-by: Priya Vijayan <priya.vijayan@intel.com>
13 ---
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
21
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.
29  
30 +config INPUT_MTDEV
31 +        tristate "Multitouch interface"
32 +        help
33 +         Say  Y here if you want to enable Multi-touch input driver for event devices 
34 +         If unsure, say N.
35 +       
36 +         To compile this driver as a module, choose M here:the
37 +         module will be called mtdev.
38 +
39  config INPUT_EVBUG
40         tristate "Event debugging"
41         help
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
51  
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 = {
59         ABS_MT_BLOB_ID,
60         ABS_MT_TRACKING_ID,
61         ABS_MT_PRESSURE,
62 +       ABS_MT_CONTACT_COUNT,
63         0
64  };
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
67 new file mode 100644
68 index 0000000..8b01220
69 --- /dev/null
70 +++ b/drivers/input/mtdev.c
71 @@ -0,0 +1,312 @@
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>
79 +
80 +#define MTDEV_MAX_POINTERS 5
81 +
82 +#ifndef ABS_MT_PRESSURE
83 +#define ABS_MT_PRESSURE 0x3a
84 +#endif
85 +#ifndef ABS_MT_CONTACT_COUNT
86 +#define ABS_MT_CONTACT_COUNT 0x3b
87 +#endif
88 +
89 +struct mtdev_input_dev
90 +{
91 +       struct input_dev* input_dev;
92 +       int id;
93 +       bool ready;
94 +       int x;
95 +       int y;
96 +       int z;
97 +       int touch;
98 +};
99 +
100 +struct mtdev_dev
101 +{
102 +       int count;
103 +       int last_count;
104 +       wait_queue_head_t wq;
105 +       struct input_handle handle;
106 +       struct mtdev_input_dev devs[MTDEV_MAX_POINTERS];
107 +};
108 +
109 +//id==-1 means to find an empty slot
110 +static int find_match_id(struct mtdev_dev * mtdev,int id)
111 +{
112 +       int i=0;
113 +
114 +       for (i=0;i<MTDEV_MAX_POINTERS;i++)
115 +       {
116 +               if(mtdev->devs[i].id==id)
117 +               {
118 +                       return i;
119 +               }
120 +       }
121 +       return -1;
122 +}
123 +
124 +
125 +static int mtdev_kt(void *data)
126 +{
127 +       struct mtdev_dev *mtdev=(struct mtdev_dev*)data;
128 +       int i=0;
129 +       int err=0;
130 +       printk("mtdev_kt entered\n");
131 +       if(!mtdev)
132 +               return -1;
133 +       //wait_event_interruptible(mtdev->wq,kthread_should_stop());
134 +       for(;i<MTDEV_MAX_POINTERS;i++)
135 +       {
136 +               struct input_dev *pdev=NULL;
137 +               pdev=mtdev->devs[i].input_dev;
138 +
139 +               err=input_register_device(pdev);
140 +               if(err)
141 +               {
142 +                       printk("error in register mtdev %d\n",err);
143 +                       return err;
144 +               }
145 +               else
146 +                       printk("successfully registered input %d\n",i);
147 +               mtdev->devs[i].ready=true;
148 +
149 +       }
150 +       return 0;
151 +}
152 +
153 +static void mtdev_event(struct input_handle * handle, 
154 +                       unsigned int type, unsigned int code, int value)
155 +{
156 +       static int i=0;
157 +       //int err=0;
158 +       int j=0;
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)
162 +               return;
163 +       if(type==EV_ABS)
164 +       {
165 +               switch(code)
166 +               {
167 +                       case ABS_MT_CONTACT_COUNT:
168 +                               if(value!=0)
169 +                               {
170 +                                       //we start from the first point
171 +                                       i=0;
172 +                                       //printk("mtdev:contact count is %d\n",value);
173 +                               }
174 +                               else if(value>MTDEV_MAX_POINTERS)
175 +                               {
176 +                                       value=MTDEV_MAX_POINTERS;
177 +                               }
178 +
179 +                               //found last release fingers and send release event
180 +                               for(j=0;j<MTDEV_MAX_POINTERS;j++)
181 +                               {
182 +                                       if(mtdev->devs[j].touch==0
183 +                                               &&mtdev->devs[j].id!=-1)
184 +                                       {
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;
189 +                                       }
190 +                                       mtdev->devs[j].touch=0;
191 +                               }
192 +                               mtdev->count=value;
193 +                               
194 +                               mtdev->last_count=value;
195 +
196 +                               break;
197 +                       case ABS_MT_TRACKING_ID:
198 +                               {
199 +                                       i=find_match_id(mtdev,value);
200 +                                       if(i==-1||i>=MTDEV_MAX_POINTERS)
201 +                                       {
202 +                                               i=find_match_id(mtdev,-1);
203 +                                               if(i==-1||i>=MTDEV_MAX_POINTERS)
204 +                                               {
205 +                                                       printk("no empty slot for id %d\n",value);
206 +                                                       break;
207 +                                               }
208 +                                               else
209 +                                               {
210 +                                                       //newly pressed 
211 +                                                       mtdev->devs[i].touch=2;
212 +                                                       mtdev->devs[i].id=value;
213 +                                                       printk("found slot %d for id %d\n",i,value);
214 +                                                       break;
215 +                                               }
216 +                                       }
217 +                                       //printk("found slot %d for id%d\n",i,value);
218 +                                       //keep the point
219 +                                       mtdev->devs[i].touch=1;
220 +                                       
221 +                               }
222 +                               break;
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);
227 +                               break;
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);
232 +                               break;
233 +                       case ABS_MT_PRESSURE:
234 +                               if(i<MTDEV_MAX_POINTERS&&i!=-1)
235 +                                       mtdev->devs[i].z=value;
236 +                               break;
237 +                       default:
238 +                               break;
239 +               }
240 +       }
241 +       else if(type == EV_SYN && code == SYN_MT_REPORT)
242 +       {
243 +               if(i<MTDEV_MAX_POINTERS&&i!=-1)
244 +               {
245 +                       if(mtdev->devs[i].touch==2)
246 +                       {
247 +                               input_report_key(mtdev->devs[i].input_dev,BTN_TOUCH,1);
248 +
249 +                       }
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);
255 +                       //i++;
256 +               }
257 +       }
258 +
259 +}
260 +/*
261 + * grab all the input of mt device, create new single touch input devices
262 + *
263 + */
264 +static int mtdev_connect(struct input_handler *handler, struct input_dev *dev,
265 +               const struct input_device_id *id)
266 +{
267 +       struct mtdev_dev* mtdev;
268 +       struct task_struct * task=NULL;
269 +       int i=0;
270 +       int err=0;
271 +       printk("mtdev_connect\n");
272 +       mtdev=kzalloc(sizeof(struct mtdev_dev),GFP_KERNEL);
273 +       if(!mtdev)
274 +               return -ENOMEM;
275 +       mtdev->handle.dev=input_get_device(dev);
276 +       mtdev->handle.name="mtdev";
277 +       mtdev->handle.handler=handler;
278 +       mtdev->handle.private=mtdev;
279 +       mtdev->count=0;
280 +       mtdev->last_count=0;
281 +       init_waitqueue_head(&mtdev->wq);
282 +       for(;i<MTDEV_MAX_POINTERS;i++)
283 +       {
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)
292 +                       return -ENOMEM;
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));
297 +
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));
301 +
302 +               pdev->name="mtdev virtual input";
303 +       }
304 +
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");
308 +       if(!task)
309 +               printk("error !!!!\n");
310 +       else
311 +               printk("kthread created OK\n");
312 +
313 +
314 +       err=input_grab_device(&mtdev->handle);
315 +       if(err)
316 +       {
317 +               printk("error in grab device %d\n",err);
318 +               return err;
319 +       }
320 +       else
321 +               printk("successfully grab device \n");
322 +
323 +       wake_up_all(&mtdev->wq);
324 +       return 0;
325 +}
326 +
327 +static void mtdev_disconnect(struct input_handle *handle)
328 +{
329 +       printk("mtdev_disconnect\n");
330 +       input_release_device(handle);
331 +}
332 +
333 +static const struct input_device_id mtdev_ids[] = {
334 +       {
335 +               .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
336 +               .vendor=0x1f87,
337 +               .product=0x0002,
338 +       },
339 +       {
340 +               .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
341 +               .vendor=0x1f87,
342 +               .product=0x0001,
343 +       },
344 +       {       
345 +               .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
346 +               .vendor=0x0483,
347 +               .product=0x3261, 
348 +       },
349 +       {
350 +               .flags=INPUT_DEVICE_ID_MATCH_VENDOR|INPUT_DEVICE_ID_MATCH_PRODUCT,
351 +               .vendor=0x2087,
352 +               .product=0x0a01,
353 +       },
354 +       {},
355 +};
356 +
357 +MODULE_DEVICE_TABLE(input,mtdev_ids);
358 +
359 +static struct input_handler mtdev_handler = {
360 +       .event          = mtdev_event,
361 +       .connect        = mtdev_connect,
362 +       .disconnect     = mtdev_disconnect,
363 +       .name           = "mtdev",
364 +       .id_table       = mtdev_ids,
365 +};
366 +
367 +
368 +static int __init mtdev_init(void)
369 +{
370 +       return input_register_handler(&mtdev_handler);
371 +}
372 +
373 +static void __exit mtdev_exit(void)
374 +{
375 +       input_unregister_handler(&mtdev_handler);
376 +}
377 +
378 +module_init(mtdev_init);
379 +module_exit(mtdev_exit);
380 +
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 */
393  
394  #define ABS_MAX                        0x3f
395  #define ABS_CNT                        (ABS_MAX+1)
396 -- 
397 1.6.2.2
398