]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/input/lib/src/l4evdev.c
Some minor fixes.
[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         struct l4input l4event;
61 };
62
63 /** l4evdev device structure */
64 struct l4evdev {
65         int exists;
66         int isopen;
67         int devn;
68         char name[16];
69         struct input_handle handle;
70
71         /* for touchpads */
72         unsigned int pkt_count;
73         int old_x[4], old_y[4];
74         int frac_dx, frac_dy;
75         unsigned long touch;
76 };
77
78 struct l4evdev *pcspkr;
79
80 /** all known devices */
81 static struct l4evdev l4evdev_devices[L4EVDEV_DEVICES];
82 /** global event list */
83 static struct l4evdev_event l4evdev_buffer[L4EVDEV_BUFFER];
84 static int l4evdev_buffer_head = 0;
85 static int l4evdev_buffer_tail = 0;
86 #define DEVS    l4evdev_devices
87 #define BUFFER  l4evdev_buffer
88 #define HEAD    l4evdev_buffer_head /**< next event slot */
89 #define TAIL    l4evdev_buffer_tail /**< first-in event if !(HEAD==TAIL) */
90 #define INC(x)  (x) = ((x) + 1) % L4EVDEV_BUFFER
91
92 static pthread_mutex_t l4evdev_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
93
94 /*************************
95  *** TOUCHPAD HANDLING ***
96  *************************/
97 /* convert absolute to relative events for inappropriate devices like touchpads
98  * (taken from input/mousedev.c) */
99 static unsigned int tpad_touch(struct l4evdev *mousedev, int value)
100 {
101         if (!value) {
102 /* FIXME tap support */
103 #if 0
104                 if (mousedev->touch &&
105                     time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
106                         /*
107                          * Toggle left button to emulate tap.
108                          * We rely on the fact that mousedev_mix always has 0
109                          * motion packet so we won't mess current position.
110                          */
111                         set_bit(0, &mousedev->packet.buttons);
112                         set_bit(0, &mousedev_mix.packet.buttons);
113                         mousedev_notify_readers(mousedev, &mousedev_mix.packet);
114                         mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
115                         clear_bit(0, &mousedev->packet.buttons);
116                         clear_bit(0, &mousedev_mix.packet.buttons);
117                 }
118 #endif
119                 mousedev->touch = mousedev->pkt_count = 0;
120                 mousedev->frac_dx = 0;
121                 mousedev->frac_dy = 0;
122         }
123         else
124                 if (!mousedev->touch)
125                         mousedev->touch = jiffies;
126
127         /* FIXME tap support */
128         return KEY_RESERVED;
129 }
130
131 static unsigned int tpad_trans_key(unsigned int code)
132 {
133         unsigned int button;
134
135         switch (code) {
136
137         /* not translated */
138         case BTN_LEFT:
139         case BTN_RIGHT:
140         case BTN_MIDDLE:
141         case BTN_SIDE:
142         case BTN_EXTRA:
143                 button = code;
144                 break;
145
146         /* translations */
147         case BTN_TOUCH:
148         case BTN_0:
149                 button = BTN_LEFT;
150                 break;
151         case BTN_1:
152                 button = BTN_RIGHT;
153                 break;
154         case BTN_2:
155                 button = BTN_MIDDLE;
156                 break;
157         case BTN_3:
158                 button = BTN_SIDE;
159                 break;
160         case BTN_4:
161                 button = BTN_EXTRA;
162                 break;
163
164         /* abort per default */
165         default:
166                 button = KEY_RESERVED;
167         }
168
169         return button;
170 }
171
172 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
173 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
174
175 /* check event and convert if appropriate
176  * returns 1 if event should be ignored */
177 static int tpad_event(struct input_dev *dev, struct l4evdev *mousedev,
178                       unsigned int *type0, unsigned int *code0, int *value0)
179 {
180         int size, tmp;
181         unsigned int type = *type0;
182         unsigned int code = *code0;
183         int value         = *value0;
184         enum { FRACTION_DENOM = 128 };
185
186         /* is it really a touchpad ? */
187         if (!test_bit(BTN_TOOL_FINGER, dev->keybit))
188                 return 0;
189
190         switch (type) {
191
192         case EV_KEY:
193                 /* from input/mousedev.c:315 */
194
195                 /* ignore */
196                 if (value == 2) return 1;
197
198                 if (code == BTN_TOUCH)
199                         code = tpad_touch(mousedev, value);
200                 else
201                         code = tpad_trans_key(code);
202
203                 /* ignore some unhandled codes */
204                 if (code == KEY_RESERVED) return 1;
205                 break;
206
207
208         case EV_SYN:
209                 /* from input/mousedev.c:324 */
210
211                 if (code == SYN_REPORT) {
212                         if (mousedev->touch) {
213                                 mousedev->pkt_count++;
214                                 /* Input system eats duplicate events, but we need all of them
215                                  * to do correct averaging so apply present one forward
216                                  */
217                                 fx(0) = fx(1);
218                                 fy(0) = fy(1);
219                         }
220                 }
221
222                 break;
223
224
225         case EV_ABS:
226                 /* from input/mousedev.c:119 */
227
228                 /* ignore if pad was not touched */
229                 if (!mousedev->touch) return 1;
230
231                 size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
232                 if (size == 0) size = 256 * 2;
233                 switch (code) {
234                 case ABS_X:
235                         fx(0) = value;
236                         /* ignore events with insufficient state */
237                         if (mousedev->pkt_count < 2) return 1;
238
239                         tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
240                         tmp += mousedev->frac_dx;
241                         value = tmp / FRACTION_DENOM;
242                         mousedev->frac_dx = tmp - value * FRACTION_DENOM;
243                         code = REL_X;
244                         type = EV_REL;
245                         break;
246
247                 case ABS_Y:
248                         fy(0) = value;
249                         /* ignore events with insufficient state */
250                         if (mousedev->pkt_count < 2) return 1;
251
252                         tmp = ((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
253                         tmp += mousedev->frac_dy;
254                         value = tmp / FRACTION_DENOM;
255                         mousedev->frac_dy = tmp - value * FRACTION_DENOM;
256                         code = REL_Y;
257                         type = EV_REL;
258                         break;
259
260                 default: /* ignore this event */
261                         return 1;
262                 }
263                 break;
264
265         default:
266                 /* ignore unknown events */
267 #if DEBUG_L4EVDEV
268                 printf("l4evdev.c: tpad ignored. D: %s, T: %d, C: %d, V: %d\n",
269                        mousedev->handle.dev->phys, type, code, value);
270 #endif
271                 return 1;
272         }
273
274         /* propagate handled events */
275         *type0 = type;
276         *code0 = code;
277         *value0 = value;
278         return 0;
279 }
280
281 /** SOME EVENTS ARE FILTERED OUT **/
282 static inline int filter_event(struct input_handle *handle, unsigned int type,
283                                unsigned int code, int value)
284 {
285         /* filter sound driver events */
286         if (test_bit(EV_SND, handle->dev->evbit))
287           return 1;
288
289         /* filter misc event: scancode -- no handlers yet */
290         if ((type == EV_MSC) && (code == MSC_SCAN))
291           return 1;
292
293         /* accepted */
294         return 0;
295 }
296
297
298 /** HANDLE INCOMING EVENTS (CALLBACK VARIANT) **/
299 static L4_CV void(*callback)(struct l4input *) = NULL;
300
301 static void l4evdev_event_cb(struct input_handle *handle, unsigned int type,
302                              unsigned int code, int value)
303 {
304 #if DEBUG_L4EVDEV
305         static unsigned long count = 0;
306 #endif
307         static struct l4input ev;
308
309         /* handle touchpads */
310         if (0)
311         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
312                        &type, &code, &value))
313                 return;
314
315         /* event filter */
316         if (filter_event(handle, type, code, value)) return;
317
318         ev.time = l4_kip_clock(l4re_kip());
319         ev.type = type;
320         ev.code = code;
321         ev.value = value;
322         ev.stream_id = (l4_umword_t)handle->dev;
323
324         /* call back */
325         callback(&ev);
326
327 #if DEBUG_L4EVDEV
328         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
329                count++, handle->dev->phys, type, code, value);
330 #endif
331 }
332
333 /** HANDLE INCOMING EVENTS (BUFFER AND PULL VARIANT) **/
334 static void l4evdev_event(struct input_handle *handle, unsigned int type,
335                           unsigned int code, int value)
336 {
337 #if DEBUG_L4EVDEV
338         static unsigned long count = 0;
339 #endif
340         struct l4evdev *evdev = handle->private;
341         l4_kernel_clock_t clk = l4_kip_clock(l4re_kip());
342
343         /* handle touchpads */
344         if (0)
345         if (tpad_event(handle->dev, (struct l4evdev *)handle->private,
346                        &type, &code, &value))
347                 return;
348
349         /* event filter */
350         if (filter_event(handle, type, code, value)) return;
351
352         pthread_mutex_lock(&l4evdev_lock);
353
354         BUFFER[HEAD].evdev = evdev;
355         BUFFER[HEAD].l4event.time = clk;
356         BUFFER[HEAD].l4event.type = type;
357         BUFFER[HEAD].l4event.code = code;
358         BUFFER[HEAD].l4event.value = value;
359         BUFFER[HEAD].l4event.stream_id = (l4_umword_t)handle->dev;
360
361         INC(HEAD);
362
363         /* check head and tail */
364         if (HEAD == TAIL) {
365                 /* clear oldest event struct in buffer */
366                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
367                 INC(TAIL);
368         }
369
370         pthread_mutex_unlock(&l4evdev_lock);
371
372 #if DEBUG_L4EVDEV
373         printf("l4evdev.c: Ev[%ld]. D: %s, T: %d, C: %d, V: %d\n",
374                count++, handle->dev->phys, type, code, value);
375 #endif
376 }
377
378 struct l4evdev *get_next_evdev(int *devnp)
379 {
380         int devn;
381
382         for (devn = 0; (devn < L4EVDEV_DEVICES) && (DEVS[devn].exists); devn++)
383           ;
384
385         if (devn == L4EVDEV_DEVICES) {
386                 printf("l4evdev.c: no more free l4evdev devices\n");
387                 return NULL;
388         }
389
390         *devnp = devn;
391
392         return &DEVS[devn];
393 }
394
395 /* XXX had connect/disconnect to be locked? */
396
397 static struct input_handle * l4evdev_connect(struct input_handler *handler,
398                                              struct input_dev *dev,
399                                              struct input_device_id *id)
400 {
401         int devn;
402         struct l4evdev *evdev = get_next_evdev(&devn);
403
404         if (!evdev)
405                 return NULL;
406
407         memset(evdev, 0, sizeof (struct l4evdev));
408
409         evdev->exists = 1;
410         evdev->devn = devn;
411
412         sprintf(evdev->name, "event%d", devn);
413
414         evdev->handle.dev = dev;
415         evdev->handle.name = evdev->name;
416         evdev->handle.handler = handler;
417         evdev->handle.private = evdev;
418
419         input_open_device(&evdev->handle);
420
421         printf("connect \"%s\", %s\n", dev->name, dev->phys);
422
423         if (test_bit(EV_SND, dev->evbit))
424                 pcspkr = evdev;
425
426         return &evdev->handle;
427 }
428
429 static void l4evdev_disconnect(struct input_handle *handle)
430 {
431         struct l4evdev *evdev = handle->private;
432
433         evdev->exists = 0;
434
435         if (evdev->isopen)
436                 input_close_device(handle);
437                 if (test_bit(EV_SND, handle->dev->evbit))
438                         pcspkr = NULL;
439         else /* XXX what about pending events? */
440                 memset(&DEVS[evdev->devn], 0, sizeof(struct l4evdev));
441 }
442
443 static struct input_device_id l4evdev_ids[] = {
444         { .driver_info = 1 },  /* Matches all devices */
445         { },                   /* Terminating zero entry */
446 };
447
448 static struct input_handler l4evdev_handler = {
449         .event =      NULL,               /* fill it on init() */
450         .connect =    l4evdev_connect,
451         .disconnect = l4evdev_disconnect,
452         .fops =       NULL,               /* not used */
453         .minor =      0,                  /* not used */
454         .name =       "l4evdev",
455         .id_table =   l4evdev_ids
456 };
457
458 /*****************************************************************************/
459
460 static int l4evdev_ispending(void)
461 {
462         return !(HEAD==TAIL);
463 }
464
465 static int l4evdev_flush(void *buf, int count)
466 {
467         int num = 0;
468         struct l4input *buffer = buf;
469
470         pthread_mutex_lock(&l4evdev_lock);
471
472         while ((TAIL!=HEAD) && count) {
473                 /* flush event buffer */
474                 *buffer = BUFFER[TAIL].l4event;
475
476                 //memset(&BUFFER[TAIL], 0, sizeof(struct l4evdev_event));
477
478                 num++; count--;
479                 INC(TAIL);
480                 buffer ++;
481         }
482
483         pthread_mutex_unlock(&l4evdev_lock);
484
485         return num;
486 }
487
488 static void l4_input_fill_info(struct input_dev *dev, l4re_event_stream_info_t *info)
489 {
490         memset(info, 0, sizeof(*info));
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 const *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(L4_CV 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_register_ux(struct input_dev *dev)
587 {
588         int devn;
589         struct l4evdev *evdev = get_next_evdev(&devn);
590
591         if (!evdev)
592                 return;
593
594         printf("EVDEV-NR: %d\n", devn);
595
596         evdev->exists = 1;
597         evdev->devn = devn;
598
599         sprintf(evdev->name, "event%d", devn);
600
601         evdev->handle.dev = dev;
602         evdev->handle.name = evdev->name;
603         evdev->handle.handler = 0;
604         evdev->handle.private = evdev;
605 }
606
607 void l4input_internal_l4evdev_exit(void)
608 {
609         input_unregister_handler(&l4evdev_handler);
610 }