]> 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 L4_CV 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         /* handle touchpads */
313         if (0)
314         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
315                        &type, &code, &value))
316                 return;
317
318         /* event filter */
319         if (filter_event(handle, type, code, value)) return;
320
321         ev.time = l4_kip_clock(l4re_kip());
322         ev.type = type;
323         ev.code = code;
324         ev.value = value;
325         ev.stream_id = (l4_umword_t)handle->dev;
326
327         /* call back */
328         callback(&ev);
329
330 #if DEBUG_L4EVDEV
331         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
332                count++, handle->dev->phys, type, code, value);
333 #endif
334 }
335
336 /** HANDLE INCOMING EVENTS (BUFFER AND PULL VARIANT) **/
337 static void l4evdev_event(struct input_handle *handle, unsigned int type,
338                           unsigned int code, int value)
339 {
340 #if DEBUG_L4EVDEV
341         static unsigned long count = 0;
342 #endif
343         struct l4evdev *evdev = handle->private;
344         l4_kernel_clock_t clk = l4_kip_clock(l4re_kip());
345
346         /* handle touchpads */
347         if (0)
348         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
349                        &type, &code, &value))
350                 return;
351
352         /* event filter */
353         if (filter_event(handle, type, code, value)) return;
354
355         pthread_mutex_lock(&l4evdev_lock);
356
357         BUFFER[HEAD].evdev = evdev;
358         BUFFER[HEAD].l4event.time = clk;
359         BUFFER[HEAD].event.type = type;
360         BUFFER[HEAD].event.code = code;
361         BUFFER[HEAD].event.value = value;
362         BUFFER[HEAD].l4event.stream_id = (l4_umword_t)handle->dev;
363
364         INC(HEAD);
365
366         /* check head and tail */
367         if (HEAD == TAIL) {
368                 /* clear oldest event struct in buffer */
369                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
370                 INC(TAIL);
371         }
372
373         pthread_mutex_unlock(&l4evdev_lock);
374
375 #if DEBUG_L4EVDEV
376         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
377                count++, handle->dev->phys, type, code, value);
378 #endif
379 }
380
381 struct l4evdev *get_next_evdev(int *devnp)
382 {
383         int devn;
384
385         for (devn = 0; (devn < L4EVDEV_DEVICES) && (DEVS[devn].exists); devn++)
386           ;
387
388         if (devn == L4EVDEV_DEVICES) {
389                 printf("l4evdev.c: no more free l4evdev devices\n");
390                 return NULL;
391         }
392
393         *devnp = devn;
394
395         return &DEVS[devn];
396 }
397
398 /* XXX had connect/disconnect to be locked? */
399
400 static struct input_handle * l4evdev_connect(struct input_handler *handler,
401                                              struct input_dev *dev,
402                                              struct input_device_id *id)
403 {
404         int devn;
405         struct l4evdev *evdev = get_next_evdev(&devn);
406
407         if (!evdev)
408                 return NULL;
409
410         memset(evdev, 0, sizeof (struct l4evdev));
411
412         evdev->exists = 1;
413         evdev->devn = devn;
414
415         sprintf(evdev->name, "event%d", devn);
416
417         evdev->handle.dev = dev;
418         evdev->handle.name = evdev->name;
419         evdev->handle.handler = handler;
420         evdev->handle.private = evdev;
421
422         input_open_device(&evdev->handle);
423
424         printf("connect \"%s\", %s\n", dev->name, dev->phys);
425
426         if (test_bit(EV_SND, dev->evbit))
427                 pcspkr = evdev;
428
429         return &evdev->handle;
430 }
431
432 static void l4evdev_disconnect(struct input_handle *handle)
433 {
434         struct l4evdev *evdev = handle->private;
435
436         evdev->exists = 0;
437
438         if (evdev->isopen)
439                 input_close_device(handle);
440                 if (test_bit(EV_SND, handle->dev->evbit))
441                         pcspkr = NULL;
442         else /* XXX what about pending events? */
443                 memset(&DEVS[evdev->devn], 0, sizeof(struct l4evdev));
444 }
445
446 static struct input_device_id l4evdev_ids[] = {
447         { .driver_info = 1 },  /* Matches all devices */
448         { },                   /* Terminating zero entry */
449 };
450
451 static struct input_handler l4evdev_handler = {
452         .event =      NULL,               /* fill it on init() */
453         .connect =    l4evdev_connect,
454         .disconnect = l4evdev_disconnect,
455         .fops =       NULL,               /* not used */
456         .minor =      0,                  /* not used */
457         .name =       "l4evdev",
458         .id_table =   l4evdev_ids
459 };
460
461 /*****************************************************************************/
462
463 static int l4evdev_ispending(void)
464 {
465         return !(HEAD==TAIL);
466 }
467
468 static int l4evdev_flush(void *buf, int count)
469 {
470         int num = 0;
471         struct l4input *buffer = buf;
472
473         pthread_mutex_lock(&l4evdev_lock);
474
475         while ((TAIL!=HEAD) && count) {
476                 /* flush event buffer */
477                 /* XXX if sizeof(struct l4input) and sizeof(struct input_event) differ
478                    memcpy is not enough  */
479
480
481                 buffer->time = BUFFER[TAIL].l4event.time;
482                 buffer->type = BUFFER[TAIL].event.type;
483                 buffer->code = BUFFER[TAIL].event.code;
484                 buffer->value = BUFFER[TAIL].event.value;
485                 buffer->stream_id = BUFFER[TAIL].l4event.stream_id;
486
487                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
488
489                 num++; count--;
490                 INC(TAIL);
491                 buffer ++;
492         }
493
494         pthread_mutex_unlock(&l4evdev_lock);
495
496         return num;
497 }
498
499 static void l4_input_fill_info(struct input_dev *dev, l4re_event_stream_info_t *info)
500 {
501         info->stream_id = (l4_umword_t)dev;
502
503         info->id.bustype = dev->id.bustype;
504         info->id.vendor  = dev->id.vendor;
505         info->id.product = dev->id.product;
506         info->id.version = dev->id.version;
507 #define COPY_BITS(n) memcpy(info->n ##s, dev->n, min(sizeof(info->n ##s), sizeof(dev->n)))
508
509         COPY_BITS(evbit);
510         COPY_BITS(keybit);
511         COPY_BITS(relbit);
512         COPY_BITS(absbit);
513 #undef COPY_BITS
514 }
515
516
517 L4_CV int
518 l4evdev_stream_info_for_id(l4_umword_t id, l4re_event_stream_info_t *si)
519 {
520         unsigned devn;
521         for (devn = 0; devn < L4EVDEV_DEVICES; devn++) {
522                 if (!DEVS[devn].exists)
523                         continue;
524                 if ((l4_umword_t)DEVS[devn].handle.dev == id) {
525                         l4_input_fill_info(DEVS[devn].handle.dev, si);
526                         return 0;
527                 }
528         }
529
530         return -L4_EINVAL;
531 }
532
533 L4_CV int
534 l4evdev_absinfo(l4_umword_t id, unsigned naxes, unsigned *axes,
535                 l4re_event_absinfo_t *infos)
536 {
537         unsigned devn, idx;
538         struct input_dev *dev;
539         for (devn = 0; devn < L4EVDEV_DEVICES; devn++) {
540                 if (!DEVS[devn].exists)
541                         continue;
542                 if ((l4_umword_t)DEVS[devn].handle.dev == id) {
543                         break;
544                 }
545         }
546
547         if (devn == L4EVDEV_DEVICES)
548                 return -L4_EINVAL;
549
550         dev = DEVS[devn].handle.dev;
551         for (idx = 0; idx < naxes; idx++) {
552                 unsigned a = axes[idx];
553                 if (a > ABS_MAX)
554                         return -L4_EINVAL;
555
556                 infos[idx].value = 0;
557                 infos[idx].min = dev->absmin[a];
558                 infos[idx].max = dev->absmax[a];
559                 infos[idx].fuzz = dev->absfuzz[a];
560                 infos[idx].flat = dev->absflat[a];
561                 infos[idx].resolution = 0;
562         }
563         return 0;
564 }
565
566 static int l4evdev_pcspkr(int tone)
567 {
568         if (!pcspkr)
569                 return -L4_ENODEV;
570
571         input_event(pcspkr->handle.dev, EV_SND, SND_TONE, tone);
572
573         return 0;
574 }
575
576 static struct l4input_ops ops = {
577         l4evdev_ispending, l4evdev_flush, l4evdev_pcspkr
578 };
579
580 struct l4input_ops * l4input_internal_l4evdev_init(L4_CV void (*cb)(struct l4input *))
581 {
582         if (cb) {
583                 /* do callbacks */
584                 callback = cb;
585                 l4evdev_handler.event = l4evdev_event_cb;
586         } else {
587                 /* buffer events in ring buffer */
588                 l4evdev_handler.event = l4evdev_event;
589         }
590
591         input_register_handler(&l4evdev_handler);
592
593         return &ops;
594 }
595
596 void l4input_internal_register_ux(struct input_dev *dev)
597 {
598         int devn;
599         struct l4evdev *evdev = get_next_evdev(&devn);
600
601         if (!evdev)
602                 return;
603
604         printf("EVDEV-NR: %d\n", devn);
605
606         evdev->exists = 1;
607         evdev->devn = devn;
608
609         sprintf(evdev->name, "event%d", devn);
610
611         evdev->handle.dev = dev;
612         evdev->handle.name = evdev->name;
613         evdev->handle.handler = 0;
614         evdev->handle.private = evdev;
615 }
616
617 void l4input_internal_l4evdev_exit(void)
618 {
619         input_unregister_handler(&l4evdev_handler);
620 }