]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
483862ae227a9f2d015ce30ca3369efbef68220a
[thirdparty/openembedded/openembedded-core-contrib.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