1/*
2 * Copyright © 2004 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <kdrive-config.h>
25#endif
26#include <errno.h>
27#include <linux/input.h>
28#include <X11/X.h>
29#include <X11/Xproto.h>
30#include <X11/Xpoll.h>
31#include "inputstr.h"
32#include "scrnintstr.h"
33#include "kdrive.h"
34
35#define NUM_EVENTS  128
36#define ABS_UNSET   -65535
37
38#define BITS_PER_LONG (sizeof(long) * 8)
39#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
40#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y))
41#define OFF(x)   ((x)%BITS_PER_LONG)
42#define LONG(x)  ((x)/BITS_PER_LONG)
43#define BIT(x)         (1 << OFF(x))
44
45typedef struct _kevdev {
46    /* current device state */
47    int                            rel[REL_MAX + 1];
48    int                            abs[ABS_MAX + 1];
49    int                            prevabs[ABS_MAX + 1];
50    long                    key[NBITS(KEY_MAX + 1)];
51
52    /* supported device info */
53    long                    relbits[NBITS(REL_MAX + 1)];
54    long                    absbits[NBITS(ABS_MAX + 1)];
55    long                    keybits[NBITS(KEY_MAX + 1)];
56    struct input_absinfo    absinfo[ABS_MAX + 1];
57    int                            max_rel;
58    int                            max_abs;
59
60    int                     fd;
61} Kevdev;
62
63static void
64EvdevPtrBtn (KdPointerInfo    *pi, struct input_event *ev)
65{
66    int flags = KD_MOUSE_DELTA | pi->buttonState;
67
68    if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) {
69        switch (ev->code) {
70        case BTN_LEFT:
71            if (ev->value == 1)
72                flags |= KD_BUTTON_1;
73	    else
74                flags &= ~KD_BUTTON_1;
75             break;
76        case BTN_MIDDLE:
77            if (ev->value == 1)
78                flags |= KD_BUTTON_2;
79	    else
80		flags &= ~KD_BUTTON_2;
81            break;
82        case BTN_RIGHT:
83            if (ev->value == 1)
84                flags |= KD_BUTTON_3;
85	    else
86		flags &= ~KD_BUTTON_3;
87            break;
88        default:
89            /* Unknow button */
90            break;
91        }
92
93        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
94    }
95}
96static void
97EvdevPtrMotion (KdPointerInfo    *pi, struct input_event *ev)
98{
99    Kevdev                *ke = pi->driverPrivate;
100    int i;
101    int flags = KD_MOUSE_DELTA | pi->buttonState;
102
103    for (i = 0; i <= ke->max_rel; i++)
104        if (ke->rel[i])
105        {
106            int a;
107            for (a = 0; a <= ke->max_rel; a++)
108            {
109                if (ISBITSET (ke->relbits, a))
110		{
111                    if (a == 0)
112                        KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0);
113                    else if (a == 1)
114                        KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0);
115                }
116		ke->rel[a] = 0;
117            }
118            break;
119        }
120    for (i = 0; i < ke->max_abs; i++)
121        if (ke->abs[i] != ke->prevabs[i])
122        {
123            int a;
124            ErrorF ("abs");
125            for (a = 0; a <= ke->max_abs; a++)
126            {
127                if (ISBITSET (ke->absbits, a))
128                    ErrorF (" %d=%d", a, ke->abs[a]);
129                ke->prevabs[a] = ke->abs[a];
130            }
131            ErrorF ("\n");
132            break;
133        }
134
135    if (ev->code == REL_WHEEL) {
136      for (i = 0; i < abs (ev->value); i++)
137      {
138        if (ev->value > 0)
139          flags |= KD_BUTTON_4;
140        else
141          flags |= KD_BUTTON_5;
142
143        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
144
145        if (ev->value > 0)
146          flags &= ~KD_BUTTON_4;
147        else
148          flags &= ~KD_BUTTON_5;
149
150        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
151      }
152    }
153
154}
155
156static void
157EvdevPtrRead (int evdevPort, void *closure)
158{
159    KdPointerInfo                *pi = closure;
160    Kevdev                       *ke = pi->driverPrivate;
161    int                        i;
162    struct input_event        events[NUM_EVENTS];
163    int                        n;
164
165    n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
166    if (n <= 0) {
167        if (errno == ENODEV)
168            DeleteInputDeviceRequest(pi->dixdev);
169        return;
170    }
171
172    n /= sizeof (struct input_event);
173    for (i = 0; i < n; i++)
174    {
175        switch (events[i].type) {
176        case EV_SYN:
177            break;
178        case EV_KEY:
179            EvdevPtrBtn (pi, &events[i]);
180            break;
181        case EV_REL:
182            ke->rel[events[i].code] += events[i].value;
183            EvdevPtrMotion (pi, &events[i]);
184            break;
185        case EV_ABS:
186            ke->abs[events[i].code] = events[i].value;
187            EvdevPtrMotion (pi, &events[i]);
188            break;
189        }
190    }
191}
192
193char *kdefaultEvdev[] =  {
194    "/dev/input/event0",
195    "/dev/input/event1",
196    "/dev/input/event2",
197    "/dev/input/event3",
198};
199
200#define NUM_DEFAULT_EVDEV    (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0]))
201
202static Status
203EvdevPtrInit (KdPointerInfo *pi)
204{
205    int                i;
206    int                fd;
207
208    if (!pi->path) {
209        for (i = 0; i < NUM_DEFAULT_EVDEV; i++) {
210            fd = open (kdefaultEvdev[i], 2);
211            if (fd >= 0) {
212                pi->path = strdup (kdefaultEvdev[i]);
213                break;
214            }
215        }
216    }
217    else {
218        fd = open (pi->path, O_RDWR);
219        if (fd < 0) {
220            ErrorF("Failed to open evdev device %s\n", pi->path);
221            return BadMatch;
222        }
223    }
224
225    close(fd);
226
227    pi->name = strdup("Evdev mouse");
228
229    return Success;
230}
231
232static Status
233EvdevPtrEnable (KdPointerInfo *pi)
234{
235    int fd;
236    unsigned long   ev[NBITS(EV_MAX)];
237    Kevdev            *ke;
238
239    if (!pi || !pi->path)
240        return BadImplementation;
241
242    fd = open(pi->path, 2);
243    if (fd < 0)
244        return BadMatch;
245
246    if (ioctl (fd, EVIOCGRAB, 1) < 0)
247        perror ("Grabbing evdev mouse device failed");
248
249    if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
250    {
251        perror ("EVIOCGBIT 0");
252        close (fd);
253        return BadMatch;
254    }
255    ke = calloc(1, sizeof (Kevdev));
256    if (!ke)
257    {
258        close (fd);
259        return BadAlloc;
260    }
261    if (ISBITSET (ev, EV_KEY))
262    {
263        if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)),
264                   ke->keybits) < 0)
265        {
266            perror ("EVIOCGBIT EV_KEY");
267            free(ke);
268            close (fd);
269            return BadMatch;
270        }
271    }
272    if (ISBITSET (ev, EV_REL))
273    {
274        if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)),
275                       ke->relbits) < 0)
276        {
277            perror ("EVIOCGBIT EV_REL");
278            free(ke);
279            close (fd);
280            return BadMatch;
281        }
282        for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
283            if (ISBITSET(ke->relbits, ke->max_rel))
284                break;
285    }
286    if (ISBITSET (ev, EV_ABS))
287    {
288        int i;
289
290        if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)),
291                   ke->absbits) < 0)
292            {
293            perror ("EVIOCGBIT EV_ABS");
294            free(ke);
295            close (fd);
296            return BadMatch;
297        }
298        for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
299            if (ISBITSET(ke->absbits, ke->max_abs))
300                break;
301        for (i = 0; i <= ke->max_abs; i++)
302        {
303            if (ISBITSET (ke->absbits, i))
304                if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0)
305                {
306                    perror ("EVIOCGABS");
307                    break;
308                }
309            ke->prevabs[i] = ABS_UNSET;
310        }
311        if (i <= ke->max_abs)
312        {
313            free(ke);
314            close (fd);
315            return BadValue;
316        }
317    }
318    if (!KdRegisterFd (fd, EvdevPtrRead, pi)) {
319        free(ke);
320        close (fd);
321        return BadAlloc;
322    }
323    pi->driverPrivate = ke;
324    ke->fd = fd;
325
326    return Success;
327}
328
329static void
330EvdevPtrDisable (KdPointerInfo *pi)
331{
332    Kevdev              *ke;
333
334    ke = pi->driverPrivate;
335
336    if (!pi || !pi->driverPrivate)
337        return;
338
339    KdUnregisterFd (pi, ke->fd, TRUE);
340
341    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
342        perror ("Ungrabbing evdev mouse device failed");
343
344    free(ke);
345    pi->driverPrivate = 0;
346}
347
348static void
349EvdevPtrFini (KdPointerInfo *pi)
350{
351}
352
353
354/*
355 * Evdev keyboard functions
356 */
357
358static void
359readMapping (KdKeyboardInfo *ki)
360{
361    if (!ki)
362        return;
363
364    ki->minScanCode = 0;
365    ki->maxScanCode = 247;
366}
367
368static void
369EvdevKbdRead (int evdevPort, void *closure)
370{
371    KdKeyboardInfo	 *ki = closure;
372    struct input_event	 events[NUM_EVENTS];
373    int			 i, n;
374
375    n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
376    if (n <= 0) {
377        if (errno == ENODEV)
378            DeleteInputDeviceRequest(ki->dixdev);
379        return;
380    }
381
382    n /= sizeof (struct input_event);
383    for (i = 0; i < n; i++)
384    {
385        if (events[i].type == EV_KEY)
386	    KdEnqueueKeyboardEvent (ki, events[i].code, !events[i].value);
387/* FIXME: must implement other types of events
388        else
389            ErrorF("Event type (%d) not delivered\n", events[i].type);
390*/
391    }
392}
393
394static Status
395EvdevKbdInit (KdKeyboardInfo *ki)
396{
397    int fd;
398
399    if (!ki->path) {
400        ErrorF("Couldn't find evdev device path\n");
401        return BadValue;
402    }
403    else {
404        fd = open (ki->path, O_RDWR);
405        if (fd < 0) {
406            ErrorF("Failed to open evdev device %s\n", ki->path);
407            return BadMatch;
408        }
409    }
410
411    close (fd);
412
413    ki->name = strdup("Evdev keyboard");
414
415    readMapping(ki);
416
417    return Success;
418}
419
420static Status
421EvdevKbdEnable (KdKeyboardInfo *ki)
422{
423    unsigned long       ev[NBITS(EV_MAX)];
424    Kevdev              *ke;
425    int                 fd;
426
427    if (!ki || !ki->path)
428        return BadImplementation;
429
430    fd = open(ki->path, O_RDWR);
431    if (fd < 0)
432        return BadMatch;
433
434    if (ioctl (fd, EVIOCGRAB, 1) < 0)
435        perror ("Grabbing evdev keyboard device failed");
436
437    if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) {
438        perror ("EVIOCGBIT 0");
439        close (fd);
440        return BadMatch;
441    }
442
443    ke = calloc(1, sizeof (Kevdev));
444    if (!ke) {
445        close (fd);
446        return BadAlloc;
447    }
448
449    if (!KdRegisterFd (fd, EvdevKbdRead, ki)) {
450        free(ke);
451        close (fd);
452        return BadAlloc;
453    }
454    ki->driverPrivate = ke;
455    ke->fd = fd;
456
457    return Success;
458}
459
460static void
461EvdevKbdLeds (KdKeyboardInfo *ki, int leds)
462{
463/*    struct input_event event;
464    Kevdev             *ke;
465
466    ki->driverPrivate = ke;
467
468    memset(&event, 0, sizeof(event));
469
470    event.type = EV_LED;
471    event.code = LED_CAPSL;
472    event.value = leds & (1 << 0) ? 1 : 0;
473    write(ke->fd, (char *) &event, sizeof(event));
474
475    event.type = EV_LED;
476    event.code = LED_NUML;
477    event.value = leds & (1 << 1) ? 1 : 0;
478    write(ke->fd, (char *) &event, sizeof(event));
479
480    event.type = EV_LED;
481    event.code = LED_SCROLLL;
482    event.value = leds & (1 << 2) ? 1 : 0;
483    write(ke->fd, (char *) &event, sizeof(event));
484
485    event.type = EV_LED;
486    event.code = LED_COMPOSE;
487    event.value = leds & (1 << 3) ? 1 : 0;
488    write(ke->fd, (char *) &event, sizeof(event));
489*/
490}
491
492static void
493EvdevKbdBell (KdKeyboardInfo *ki, int volume, int frequency, int duration)
494{
495}
496
497static void
498EvdevKbdDisable (KdKeyboardInfo *ki)
499{
500    Kevdev              *ke;
501
502    ke = ki->driverPrivate;
503
504    if (!ki || !ki->driverPrivate)
505        return;
506
507    KdUnregisterFd (ki, ke->fd, TRUE);
508
509    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
510        perror ("Ungrabbing evdev keyboard device failed");
511
512    free(ke);
513    ki->driverPrivate = 0;
514}
515
516static void
517EvdevKbdFini (KdKeyboardInfo *ki)
518{
519}
520
521KdPointerDriver LinuxEvdevMouseDriver = {
522    "evdev",
523    EvdevPtrInit,
524    EvdevPtrEnable,
525    EvdevPtrDisable,
526    EvdevPtrFini,
527    NULL,
528};
529
530KdKeyboardDriver LinuxEvdevKeyboardDriver = {
531    "evdev",
532    EvdevKbdInit,
533    EvdevKbdEnable,
534    EvdevKbdLeds,
535    EvdevKbdBell,
536    EvdevKbdDisable,
537    EvdevKbdFini,
538    NULL,
539};
540