]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/input/lib/src/l4evdev.c
update
[l4.git] / l4 / pkg / input / lib / src / l4evdev.c
1 /*****************************************************************************/
2 /**
3  * \file   input/lib/src/l4evdev.c
4  * \brief  L4INPUT Event Device
5  *
6  * \date   05/28/2003
7  * \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
8  * \author Frank Mehnert <fm3@os.inf.tu-dresden.de>
9  *
10  * This is roughly a Linux /dev/event implementation adopted from evdev.
11  *
12  * Original copyright notice from drivers/input/evdev.c follows...
13  */
14 /*
15  * Event char devices, giving access to raw input device events.
16  *
17  * Copyright (c) 1999-2002 Vojtech Pavlik
18  *
19  * This program is free software; you can redistribute it and/or modify it
20  * under the terms of the GNU General Public License version 2 as published by
21  * the Free Software Foundation.
22  */
23
24 /* L4 */
25 #include <string.h>
26 #include <l4/sys/err.h>
27 #include <l4/input/libinput.h>
28 #include <l4/re/c/util/cap_alloc.h>
29 #include <l4/re/env.h>
30 #include <linux/kernel.h>
31 #include <pthread.h>
32
33 /* C */
34 #include <stdio.h>
35
36 /* Linux */
37 #include <linux/input.h>
38 #include <linux/jiffies.h>
39
40 #include "internal.h"
41
42 /* Okay ...
43
44    There can be up to L4EVDEV_DEVICES managed. 
45
46    So we _don't_ need one event queue/list per device to support dedicated
47    event handlers per device -> we use one general event queue (for DOpE) with
48    up to L4EVDEV_BUFFER l4evdev_event structures. CON uses callbacks and
49    therefore needs no ring buffer.
50 */
51
52 #define L4EVDEV_DEVICES    16
53 #define L4EVDEV_BUFFER    512
54
55 #define DEBUG_L4EVDEV       0
56
57 /** l4evdev event structure */
58 struct l4evdev_event {
59         struct l4evdev *evdev;
60         union {
61                 struct input_event event;
62                 struct l4input l4event;
63         };
64 };
65
66 /** l4evdev device structure */
67 struct l4evdev {
68         int exists;
69         int isopen;
70         int devn;
71         char name[16];
72         struct input_handle handle;
73
74         /* for touchpads */
75         unsigned int pkt_count;
76         int old_x[4], old_y[4];
77         int frac_dx, frac_dy;
78         unsigned long touch;
79 };
80
81 struct l4evdev *pcspkr;
82
83 /** all known devices */
84 static struct l4evdev l4evdev_devices[L4EVDEV_DEVICES];
85 /** global event list */
86 static struct l4evdev_event l4evdev_buffer[L4EVDEV_BUFFER];
87 static int l4evdev_buffer_head = 0;
88 static int l4evdev_buffer_tail = 0;
89 #define DEVS    l4evdev_devices
90 #define BUFFER  l4evdev_buffer
91 #define HEAD    l4evdev_buffer_head /**< next event slot */
92 #define TAIL    l4evdev_buffer_tail /**< first-in event if !(HEAD==TAIL) */
93 #define INC(x)  (x) = ((x) + 1) % L4EVDEV_BUFFER
94
95 static pthread_mutex_t l4evdev_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
96
97 /*************************
98  *** TOUCHPAD HANDLING ***
99  *************************/
100 /* convert absolute to relative events for inappropriate devices like touchpads
101  * (taken from input/mousedev.c) */
102 static unsigned int tpad_touch(struct l4evdev *mousedev, int value)
103 {
104         if (!value) {
105 /* FIXME tap support */
106 #if 0
107                 if (mousedev->touch &&
108                     time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
109                         /*
110                          * Toggle left button to emulate tap.
111                          * We rely on the fact that mousedev_mix always has 0
112                          * motion packet so we won't mess current position.
113                          */
114                         set_bit(0, &mousedev->packet.buttons);
115                         set_bit(0, &mousedev_mix.packet.buttons);
116                         mousedev_notify_readers(mousedev, &mousedev_mix.packet);
117                         mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
118                         clear_bit(0, &mousedev->packet.buttons);
119                         clear_bit(0, &mousedev_mix.packet.buttons);
120                 }
121 #endif
122                 mousedev->touch = mousedev->pkt_count = 0;
123                 mousedev->frac_dx = 0;
124                 mousedev->frac_dy = 0;
125         }
126         else
127                 if (!mousedev->touch)
128                         mousedev->touch = jiffies;
129
130         /* FIXME tap support */
131         return KEY_RESERVED;
132 }
133
134 static unsigned int tpad_trans_key(unsigned int code)
135 {
136         unsigned int button;
137
138         switch (code) {
139
140         /* not translated */
141         case BTN_LEFT:
142         case BTN_RIGHT:
143         case BTN_MIDDLE:
144         case BTN_SIDE:
145         case BTN_EXTRA:
146                 button = code;
147                 break;
148
149         /* translations */
150         case BTN_TOUCH:
151         case BTN_0:
152                 button = BTN_LEFT;
153                 break;
154         case BTN_1:
155                 button = BTN_RIGHT;
156                 break;
157         case BTN_2:
158                 button = BTN_MIDDLE;
159                 break;
160         case BTN_3:
161                 button = BTN_SIDE;
162                 break;
163         case BTN_4:
164                 button = BTN_EXTRA;
165                 break;
166
167         /* abort per default */
168         default:
169                 button = KEY_RESERVED;
170         }
171
172         return button;
173 }
174
175 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
176 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
177
178 /* check event and convert if appropriate
179  * returns 1 if event should be ignored */
180 static int tpad_event(struct input_dev *dev, struct l4evdev *mousedev,
181                       unsigned int *type0, unsigned int *code0, int *value0)
182 {
183         int size, tmp;
184         unsigned int type = *type0;
185         unsigned int code = *code0;
186         int value         = *value0;
187         enum { FRACTION_DENOM = 128 };
188
189         /* is it really a touchpad ? */
190         if (!test_bit(BTN_TOOL_FINGER, dev->keybit))
191                 return 0;
192
193         switch (type) {
194
195         case EV_KEY:
196                 /* from input/mousedev.c:315 */
197
198                 /* ignore */
199                 if (value == 2) return 1;
200
201                 if (code == BTN_TOUCH)
202                         code = tpad_touch(mousedev, value);
203                 else
204                         code = tpad_trans_key(code);
205
206                 /* ignore some unhandled codes */
207                 if (code == KEY_RESERVED) return 1;
208                 break;
209
210
211         case EV_SYN:
212                 /* from input/mousedev.c:324 */
213
214                 if (code == SYN_REPORT) {
215                         if (mousedev->touch) {
216                                 mousedev->pkt_count++;
217                                 /* Input system eats duplicate events, but we need all of them
218                                  * to do correct averaging so apply present one forward
219                                  */
220                                 fx(0) = fx(1);
221                                 fy(0) = fy(1);
222                         }
223                 }
224
225                 break;
226
227
228         case EV_ABS:
229                 /* from input/mousedev.c:119 */
230
231                 /* ignore if pad was not touched */
232                 if (!mousedev->touch) return 1;
233
234                 size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
235                 if (size == 0) size = 256 * 2;
236                 switch (code) {
237                 case ABS_X:
238                         fx(0) = value;
239                         /* ignore events with insufficient state */
240                         if (mousedev->pkt_count < 2) return 1;
241
242                         tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
243                         tmp += mousedev->frac_dx;
244                         value = tmp / FRACTION_DENOM;
245                         mousedev->frac_dx = tmp - value * FRACTION_DENOM;
246                         code = REL_X;
247                         type = EV_REL;
248                         break;
249
250                 case ABS_Y:
251                         fy(0) = value;
252                         /* ignore events with insufficient state */
253                         if (mousedev->pkt_count < 2) return 1;
254
255                         tmp = ((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
256                         tmp += mousedev->frac_dy;
257                         value = tmp / FRACTION_DENOM;
258                         mousedev->frac_dy = tmp - value * FRACTION_DENOM;
259                         code = REL_Y;
260                         type = EV_REL;
261                         break;
262
263                 default: /* ignore this event */
264                         return 1;
265                 }
266                 break;
267
268         default:
269                 /* ignore unknown events */
270 #if DEBUG_L4EVDEV
271                 printf("l4evdev.c: tpad ignored. D: %s, T: %d, C: %d, V: %d\n",
272                        mousedev->handle.dev->phys, type, code, value);
273 #endif
274                 return 1;
275         }
276
277         /* propagate handled events */
278         *type0 = type;
279         *code0 = code;
280         *value0 = value;
281         return 0;
282 }
283
284 /** SOME EVENTS ARE FILTERED OUT **/
285 static inline int filter_event(struct input_handle *handle, unsigned int type,
286                                unsigned int code, int value)
287 {
288         /* filter sound driver events */
289         if (test_bit(EV_SND, handle->dev->evbit))
290           return 1;
291
292         /* filter misc event: scancode -- no handlers yet */
293         if ((type == EV_MSC) && (code == MSC_SCAN))
294           return 1;
295
296         /* accepted */
297         return 0;
298 }
299
300
301 /** HANDLE INCOMING EVENTS (CALLBACK VARIANT) **/
302 static void(*callback)(struct l4input *) = NULL;
303
304 static void l4evdev_event_cb(struct input_handle *handle, unsigned int type,
305                              unsigned int code, int value)
306 {
307 #if DEBUG_L4EVDEV
308         static unsigned long count = 0;
309 #endif
310         static struct l4input ev;
311
312 #if 0
313         /* handle touchpads */
314         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
315                        &type, &code, &value))
316                 return;
317 #endif
318
319         /* event filter */
320         if (filter_event(handle, type, code, value)) return;
321
322         ev.time = l4re_kip()->clock;
323         ev.type = type;
324         ev.code = code;
325         ev.value = value;
326         ev.stream_id = (l4_umword_t)handle->dev;
327
328         /* call back */
329         callback(&ev);
330
331 #if DEBUG_L4EVDEV
332         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
333                count++, handle->dev->phys, type, code, value);
334 #endif
335 }
336
337 /** HANDLE INCOMING EVENTS (BUFFER AND PULL VARIANT) **/
338 static void l4evdev_event(struct input_handle *handle, unsigned int type,
339                           unsigned int code, int value)
340 {
341 #if DEBUG_L4EVDEV
342         static unsigned long count = 0;
343 #endif
344         struct l4evdev *evdev = handle->private;
345         l4_kernel_clock_t clk = l4re_kip()->clock;
346
347 #if 0
348         /* handle touchpads */
349         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
350                        &type, &code, &value))
351                 return;
352 #endif
353
354         /* event filter */
355         if (filter_event(handle, type, code, value)) return;
356
357         pthread_mutex_lock(&l4evdev_lock);
358
359         BUFFER[HEAD].evdev = evdev;
360         BUFFER[HEAD].l4event.time = clk;
361         BUFFER[HEAD].event.type = type;
362         BUFFER[HEAD].event.code = code;
363         BUFFER[HEAD].event.value = value;
364         BUFFER[HEAD].l4event.stream_id = (l4_umword_t)handle->dev;
365
366         INC(HEAD);
367
368         /* check head and tail */
369         if (HEAD == TAIL) {
370                 /* clear oldest event struct in buffer */
371                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
372                 INC(TAIL);
373         }
374
375         pthread_mutex_unlock(&l4evdev_lock);
376
377 #if DEBUG_L4EVDEV
378         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
379                count++, handle->dev->phys, type, code, value);
380 #endif
381 }
382
383 /* XXX had connect/disconnect to be locked? */
384
385 static struct input_handle * l4evdev_connect(struct input_handler *handler,
386                                              struct input_dev *dev,
387                                              struct input_device_id *id)
388 {
389         struct l4evdev *evdev;
390         int devn;
391
392         for (devn = 0; (devn < L4EVDEV_DEVICES) && (DEVS[devn].exists); devn++);
393         if (devn == L4EVDEV_DEVICES) {
394                 printf("l4evdev.c: no more free l4evdev devices\n");
395                 return NULL;
396         }
397
398         evdev = &DEVS[devn];
399
400         memset(evdev, 0, sizeof (struct l4evdev));
401
402         evdev->exists = 1;
403         evdev->devn = devn;
404
405         sprintf(evdev->name, "event%d", devn);
406
407         evdev->handle.dev = dev;
408         evdev->handle.name = evdev->name;
409         evdev->handle.handler = handler;
410         evdev->handle.private = evdev;
411
412         input_open_device(&evdev->handle);
413
414         printf("connect \"%s\", %s\n", dev->name, dev->phys);
415
416         if (test_bit(EV_SND, dev->evbit))
417                 pcspkr = evdev;
418
419         return &evdev->handle;
420 }
421
422 static void l4evdev_disconnect(struct input_handle *handle)
423 {
424         struct l4evdev *evdev = handle->private;
425
426         evdev->exists = 0;
427
428         if (evdev->isopen)
429                 input_close_device(handle);
430                 if (test_bit(EV_SND, handle->dev->evbit))
431                         pcspkr = NULL;
432         else /* XXX what about pending events? */
433                 memset(&DEVS[evdev->devn], 0, sizeof(struct l4evdev));
434 }
435
436 static struct input_device_id l4evdev_ids[] = {
437         { .driver_info = 1 },  /* Matches all devices */
438         { },                   /* Terminating zero entry */
439 };
440
441 static struct input_handler l4evdev_handler = {
442         .event =      NULL,               /* fill it on init() */
443         .connect =    l4evdev_connect,
444         .disconnect = l4evdev_disconnect,
445         .fops =       NULL,               /* not used */
446         .minor =      0,                  /* not used */
447         .name =       "l4evdev",
448         .id_table =   l4evdev_ids
449 };
450
451 /*****************************************************************************/
452
453 static int l4evdev_ispending(void)
454 {
455         return !(HEAD==TAIL);
456 }
457
458 static int l4evdev_flush(void *buf, int count)
459 {
460         int num = 0;
461         struct l4input *buffer = buf;
462
463         pthread_mutex_lock(&l4evdev_lock);
464
465         while ((TAIL!=HEAD) && count) {
466                 /* flush event buffer */
467                 /* XXX if sizeof(struct l4input) and sizeof(struct input_event) differ
468                    memcpy is not enough  */
469
470
471                 buffer->time = BUFFER[TAIL].l4event.time;
472                 buffer->type = BUFFER[TAIL].event.type;
473                 buffer->code = BUFFER[TAIL].event.code;
474                 buffer->value = BUFFER[TAIL].event.value;
475                 buffer->stream_id = BUFFER[TAIL].l4event.stream_id;
476
477                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
478
479                 num++; count--;
480                 INC(TAIL);
481                 buffer ++;
482         }
483
484         pthread_mutex_unlock(&l4evdev_lock);
485
486         return num;
487 }
488
489 static void l4_input_fill_info(struct input_dev *dev, l4re_event_stream_info_t *info)
490 {
491         info->stream_id = (l4_umword_t)dev;
492
493         info->id.bustype = dev->id.bustype;
494         info->id.vendor  = dev->id.vendor;
495         info->id.product = dev->id.product;
496         info->id.version = dev->id.version;
497 #define COPY_BITS(n) memcpy(info->n ##s, dev->n, min(sizeof(info->n ##s), sizeof(dev->n)))
498
499         COPY_BITS(evbit);
500         COPY_BITS(keybit);
501         COPY_BITS(relbit);
502         COPY_BITS(absbit);
503 #undef COPY_BITS
504 }
505
506
507 L4_CV int
508 l4evdev_stream_info_for_id(l4_umword_t id, l4re_event_stream_info_t *si)
509 {
510         unsigned devn;
511         for (devn = 0; devn < L4EVDEV_DEVICES; devn++) {
512                 if (!DEVS[devn].exists)
513                         continue;
514                 if ((l4_umword_t)DEVS[devn].handle.dev == id) {
515                         l4_input_fill_info(DEVS[devn].handle.dev, si);
516                         return 0;
517                 }
518         }
519
520         return -L4_EINVAL;
521 }
522
523 L4_CV int
524 l4evdev_absinfo(l4_umword_t id, unsigned naxes, unsigned *axes,
525                 l4re_event_absinfo_t *infos)
526 {
527         unsigned devn, idx;
528         struct input_dev *dev;
529         for (devn = 0; devn < L4EVDEV_DEVICES; devn++) {
530                 if (!DEVS[devn].exists)
531                         continue;
532                 if ((l4_umword_t)DEVS[devn].handle.dev == id) {
533                         break;
534                 }
535         }
536
537         if (devn == L4EVDEV_DEVICES)
538                 return -L4_EINVAL;
539
540         dev = DEVS[devn].handle.dev;
541         for (idx = 0; idx < naxes; idx++) {
542                 unsigned a = axes[idx];
543                 if (a > ABS_MAX)
544                         return -L4_EINVAL;
545
546                 infos[idx].value = 0;
547                 infos[idx].min = dev->absmin[a];
548                 infos[idx].max = dev->absmax[a];
549                 infos[idx].fuzz = dev->absfuzz[a];
550                 infos[idx].flat = dev->absflat[a];
551                 infos[idx].resolution = 0;
552         }
553         return 0;
554 }
555
556 static int l4evdev_pcspkr(int tone)
557 {
558         if (!pcspkr)
559                 return -L4_ENODEV;
560
561         input_event(pcspkr->handle.dev, EV_SND, SND_TONE, tone);
562
563         return 0;
564 }
565
566 static struct l4input_ops ops = {
567         l4evdev_ispending, l4evdev_flush, l4evdev_pcspkr
568 };
569
570 struct l4input_ops * l4input_internal_l4evdev_init(void (*cb)(struct l4input *))
571 {
572         if (cb) {
573                 /* do callbacks */
574                 callback = cb;
575                 l4evdev_handler.event = l4evdev_event_cb;
576         } else {
577                 /* buffer events in ring buffer */
578                 l4evdev_handler.event = l4evdev_event;
579         }
580
581         input_register_handler(&l4evdev_handler);
582
583         return &ops;
584 }
585
586 void l4input_internal_l4evdev_exit(void)
587 {
588         input_unregister_handler(&l4evdev_handler);
589 }