1706f2543Smrg/*
2706f2543Smrg * Copyright © 2004 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_CONFIG_H
24706f2543Smrg#include <kdrive-config.h>
25706f2543Smrg#endif
26706f2543Smrg#include <errno.h>
27706f2543Smrg#include <linux/input.h>
28706f2543Smrg#include <X11/X.h>
29706f2543Smrg#include <X11/Xproto.h>
30706f2543Smrg#include <X11/Xpoll.h>
31706f2543Smrg#include "inputstr.h"
32706f2543Smrg#include "scrnintstr.h"
33706f2543Smrg#include "kdrive.h"
34706f2543Smrg
35706f2543Smrg#define NUM_EVENTS  128
36706f2543Smrg#define ABS_UNSET   -65535
37706f2543Smrg
38706f2543Smrg#define BITS_PER_LONG (sizeof(long) * 8)
39706f2543Smrg#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
40706f2543Smrg#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y))
41706f2543Smrg#define OFF(x)   ((x)%BITS_PER_LONG)
42706f2543Smrg#define LONG(x)  ((x)/BITS_PER_LONG)
43706f2543Smrg#define BIT(x)         (1 << OFF(x))
44706f2543Smrg
45706f2543Smrgtypedef struct _kevdev {
46706f2543Smrg    /* current device state */
47706f2543Smrg    int                            rel[REL_MAX + 1];
48706f2543Smrg    int                            abs[ABS_MAX + 1];
49706f2543Smrg    int                            prevabs[ABS_MAX + 1];
50706f2543Smrg    long                    key[NBITS(KEY_MAX + 1)];
51706f2543Smrg
52706f2543Smrg    /* supported device info */
53706f2543Smrg    long                    relbits[NBITS(REL_MAX + 1)];
54706f2543Smrg    long                    absbits[NBITS(ABS_MAX + 1)];
55706f2543Smrg    long                    keybits[NBITS(KEY_MAX + 1)];
56706f2543Smrg    struct input_absinfo    absinfo[ABS_MAX + 1];
57706f2543Smrg    int                            max_rel;
58706f2543Smrg    int                            max_abs;
59706f2543Smrg
60706f2543Smrg    int                     fd;
61706f2543Smrg} Kevdev;
62706f2543Smrg
63706f2543Smrgstatic void
64706f2543SmrgEvdevPtrBtn (KdPointerInfo    *pi, struct input_event *ev)
65706f2543Smrg{
66706f2543Smrg    int flags = KD_MOUSE_DELTA | pi->buttonState;
67706f2543Smrg
68706f2543Smrg    if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) {
69706f2543Smrg        switch (ev->code) {
70706f2543Smrg        case BTN_LEFT:
71706f2543Smrg            if (ev->value == 1)
72706f2543Smrg                flags |= KD_BUTTON_1;
73706f2543Smrg	    else
74706f2543Smrg                flags &= ~KD_BUTTON_1;
75706f2543Smrg             break;
76706f2543Smrg        case BTN_MIDDLE:
77706f2543Smrg            if (ev->value == 1)
78706f2543Smrg                flags |= KD_BUTTON_2;
79706f2543Smrg	    else
80706f2543Smrg		flags &= ~KD_BUTTON_2;
81706f2543Smrg            break;
82706f2543Smrg        case BTN_RIGHT:
83706f2543Smrg            if (ev->value == 1)
84706f2543Smrg                flags |= KD_BUTTON_3;
85706f2543Smrg	    else
86706f2543Smrg		flags &= ~KD_BUTTON_3;
87706f2543Smrg            break;
88706f2543Smrg        default:
89706f2543Smrg            /* Unknow button */
90706f2543Smrg            break;
91706f2543Smrg        }
92706f2543Smrg
93706f2543Smrg        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
94706f2543Smrg    }
95706f2543Smrg}
96706f2543Smrgstatic void
97706f2543SmrgEvdevPtrMotion (KdPointerInfo    *pi, struct input_event *ev)
98706f2543Smrg{
99706f2543Smrg    Kevdev                *ke = pi->driverPrivate;
100706f2543Smrg    int i;
101706f2543Smrg    int flags = KD_MOUSE_DELTA | pi->buttonState;
102706f2543Smrg
103706f2543Smrg    for (i = 0; i <= ke->max_rel; i++)
104706f2543Smrg        if (ke->rel[i])
105706f2543Smrg        {
106706f2543Smrg            int a;
107706f2543Smrg            for (a = 0; a <= ke->max_rel; a++)
108706f2543Smrg            {
109706f2543Smrg                if (ISBITSET (ke->relbits, a))
110706f2543Smrg		{
111706f2543Smrg                    if (a == 0)
112706f2543Smrg                        KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0);
113706f2543Smrg                    else if (a == 1)
114706f2543Smrg                        KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0);
115706f2543Smrg                }
116706f2543Smrg		ke->rel[a] = 0;
117706f2543Smrg            }
118706f2543Smrg            break;
119706f2543Smrg        }
120706f2543Smrg    for (i = 0; i < ke->max_abs; i++)
121706f2543Smrg        if (ke->abs[i] != ke->prevabs[i])
122706f2543Smrg        {
123706f2543Smrg            int a;
124706f2543Smrg            ErrorF ("abs");
125706f2543Smrg            for (a = 0; a <= ke->max_abs; a++)
126706f2543Smrg            {
127706f2543Smrg                if (ISBITSET (ke->absbits, a))
128706f2543Smrg                    ErrorF (" %d=%d", a, ke->abs[a]);
129706f2543Smrg                ke->prevabs[a] = ke->abs[a];
130706f2543Smrg            }
131706f2543Smrg            ErrorF ("\n");
132706f2543Smrg            break;
133706f2543Smrg        }
134706f2543Smrg
135706f2543Smrg    if (ev->code == REL_WHEEL) {
136706f2543Smrg      for (i = 0; i < abs (ev->value); i++)
137706f2543Smrg      {
138706f2543Smrg        if (ev->value > 0)
139706f2543Smrg          flags |= KD_BUTTON_4;
140706f2543Smrg        else
141706f2543Smrg          flags |= KD_BUTTON_5;
142706f2543Smrg
143706f2543Smrg        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
144706f2543Smrg
145706f2543Smrg        if (ev->value > 0)
146706f2543Smrg          flags &= ~KD_BUTTON_4;
147706f2543Smrg        else
148706f2543Smrg          flags &= ~KD_BUTTON_5;
149706f2543Smrg
150706f2543Smrg        KdEnqueuePointerEvent (pi, flags, 0, 0, 0);
151706f2543Smrg      }
152706f2543Smrg    }
153706f2543Smrg
154706f2543Smrg}
155706f2543Smrg
156706f2543Smrgstatic void
157706f2543SmrgEvdevPtrRead (int evdevPort, void *closure)
158706f2543Smrg{
159706f2543Smrg    KdPointerInfo                *pi = closure;
160706f2543Smrg    Kevdev                       *ke = pi->driverPrivate;
161706f2543Smrg    int                        i;
162706f2543Smrg    struct input_event        events[NUM_EVENTS];
163706f2543Smrg    int                        n;
164706f2543Smrg
165706f2543Smrg    n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
166706f2543Smrg    if (n <= 0) {
167706f2543Smrg        if (errno == ENODEV)
168706f2543Smrg            DeleteInputDeviceRequest(pi->dixdev);
169706f2543Smrg        return;
170706f2543Smrg    }
171706f2543Smrg
172706f2543Smrg    n /= sizeof (struct input_event);
173706f2543Smrg    for (i = 0; i < n; i++)
174706f2543Smrg    {
175706f2543Smrg        switch (events[i].type) {
176706f2543Smrg        case EV_SYN:
177706f2543Smrg            break;
178706f2543Smrg        case EV_KEY:
179706f2543Smrg            EvdevPtrBtn (pi, &events[i]);
180706f2543Smrg            break;
181706f2543Smrg        case EV_REL:
182706f2543Smrg            ke->rel[events[i].code] += events[i].value;
183706f2543Smrg            EvdevPtrMotion (pi, &events[i]);
184706f2543Smrg            break;
185706f2543Smrg        case EV_ABS:
186706f2543Smrg            ke->abs[events[i].code] = events[i].value;
187706f2543Smrg            EvdevPtrMotion (pi, &events[i]);
188706f2543Smrg            break;
189706f2543Smrg        }
190706f2543Smrg    }
191706f2543Smrg}
192706f2543Smrg
193706f2543Smrgchar *kdefaultEvdev[] =  {
194706f2543Smrg    "/dev/input/event0",
195706f2543Smrg    "/dev/input/event1",
196706f2543Smrg    "/dev/input/event2",
197706f2543Smrg    "/dev/input/event3",
198706f2543Smrg};
199706f2543Smrg
200706f2543Smrg#define NUM_DEFAULT_EVDEV    (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0]))
201706f2543Smrg
202706f2543Smrgstatic Status
203706f2543SmrgEvdevPtrInit (KdPointerInfo *pi)
204706f2543Smrg{
205706f2543Smrg    int                i;
206706f2543Smrg    int                fd;
207706f2543Smrg
208706f2543Smrg    if (!pi->path) {
209706f2543Smrg        for (i = 0; i < NUM_DEFAULT_EVDEV; i++) {
210706f2543Smrg            fd = open (kdefaultEvdev[i], 2);
211706f2543Smrg            if (fd >= 0) {
212706f2543Smrg                pi->path = strdup (kdefaultEvdev[i]);
213706f2543Smrg                break;
214706f2543Smrg            }
215706f2543Smrg        }
216706f2543Smrg    }
217706f2543Smrg    else {
218706f2543Smrg        fd = open (pi->path, O_RDWR);
219706f2543Smrg        if (fd < 0) {
220706f2543Smrg            ErrorF("Failed to open evdev device %s\n", pi->path);
221706f2543Smrg            return BadMatch;
222706f2543Smrg        }
223706f2543Smrg    }
224706f2543Smrg
225706f2543Smrg    close(fd);
226706f2543Smrg
227706f2543Smrg    pi->name = strdup("Evdev mouse");
228706f2543Smrg
229706f2543Smrg    return Success;
230706f2543Smrg}
231706f2543Smrg
232706f2543Smrgstatic Status
233706f2543SmrgEvdevPtrEnable (KdPointerInfo *pi)
234706f2543Smrg{
235706f2543Smrg    int fd;
236706f2543Smrg    unsigned long   ev[NBITS(EV_MAX)];
237706f2543Smrg    Kevdev            *ke;
238706f2543Smrg
239706f2543Smrg    if (!pi || !pi->path)
240706f2543Smrg        return BadImplementation;
241706f2543Smrg
242706f2543Smrg    fd = open(pi->path, 2);
243706f2543Smrg    if (fd < 0)
244706f2543Smrg        return BadMatch;
245706f2543Smrg
246706f2543Smrg    if (ioctl (fd, EVIOCGRAB, 1) < 0)
247706f2543Smrg        perror ("Grabbing evdev mouse device failed");
248706f2543Smrg
249706f2543Smrg    if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
250706f2543Smrg    {
251706f2543Smrg        perror ("EVIOCGBIT 0");
252706f2543Smrg        close (fd);
253706f2543Smrg        return BadMatch;
254706f2543Smrg    }
255706f2543Smrg    ke = calloc(1, sizeof (Kevdev));
256706f2543Smrg    if (!ke)
257706f2543Smrg    {
258706f2543Smrg        close (fd);
259706f2543Smrg        return BadAlloc;
260706f2543Smrg    }
261706f2543Smrg    if (ISBITSET (ev, EV_KEY))
262706f2543Smrg    {
263706f2543Smrg        if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)),
264706f2543Smrg                   ke->keybits) < 0)
265706f2543Smrg        {
266706f2543Smrg            perror ("EVIOCGBIT EV_KEY");
267706f2543Smrg            free(ke);
268706f2543Smrg            close (fd);
269706f2543Smrg            return BadMatch;
270706f2543Smrg        }
271706f2543Smrg    }
272706f2543Smrg    if (ISBITSET (ev, EV_REL))
273706f2543Smrg    {
274706f2543Smrg        if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)),
275706f2543Smrg                       ke->relbits) < 0)
276706f2543Smrg        {
277706f2543Smrg            perror ("EVIOCGBIT EV_REL");
278706f2543Smrg            free(ke);
279706f2543Smrg            close (fd);
280706f2543Smrg            return BadMatch;
281706f2543Smrg        }
282706f2543Smrg        for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
283706f2543Smrg            if (ISBITSET(ke->relbits, ke->max_rel))
284706f2543Smrg                break;
285706f2543Smrg    }
286706f2543Smrg    if (ISBITSET (ev, EV_ABS))
287706f2543Smrg    {
288706f2543Smrg        int i;
289706f2543Smrg
290706f2543Smrg        if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)),
291706f2543Smrg                   ke->absbits) < 0)
292706f2543Smrg            {
293706f2543Smrg            perror ("EVIOCGBIT EV_ABS");
294706f2543Smrg            free(ke);
295706f2543Smrg            close (fd);
296706f2543Smrg            return BadMatch;
297706f2543Smrg        }
298706f2543Smrg        for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
299706f2543Smrg            if (ISBITSET(ke->absbits, ke->max_abs))
300706f2543Smrg                break;
301706f2543Smrg        for (i = 0; i <= ke->max_abs; i++)
302706f2543Smrg        {
303706f2543Smrg            if (ISBITSET (ke->absbits, i))
304706f2543Smrg                if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0)
305706f2543Smrg                {
306706f2543Smrg                    perror ("EVIOCGABS");
307706f2543Smrg                    break;
308706f2543Smrg                }
309706f2543Smrg            ke->prevabs[i] = ABS_UNSET;
310706f2543Smrg        }
311706f2543Smrg        if (i <= ke->max_abs)
312706f2543Smrg        {
313706f2543Smrg            free(ke);
314706f2543Smrg            close (fd);
315706f2543Smrg            return BadValue;
316706f2543Smrg        }
317706f2543Smrg    }
318706f2543Smrg    if (!KdRegisterFd (fd, EvdevPtrRead, pi)) {
319706f2543Smrg        free(ke);
320706f2543Smrg        close (fd);
321706f2543Smrg        return BadAlloc;
322706f2543Smrg    }
323706f2543Smrg    pi->driverPrivate = ke;
324706f2543Smrg    ke->fd = fd;
325706f2543Smrg
326706f2543Smrg    return Success;
327706f2543Smrg}
328706f2543Smrg
329706f2543Smrgstatic void
330706f2543SmrgEvdevPtrDisable (KdPointerInfo *pi)
331706f2543Smrg{
332706f2543Smrg    Kevdev              *ke;
333706f2543Smrg
334706f2543Smrg    ke = pi->driverPrivate;
335706f2543Smrg
336706f2543Smrg    if (!pi || !pi->driverPrivate)
337706f2543Smrg        return;
338706f2543Smrg
339706f2543Smrg    KdUnregisterFd (pi, ke->fd, TRUE);
340706f2543Smrg
341706f2543Smrg    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
342706f2543Smrg        perror ("Ungrabbing evdev mouse device failed");
343706f2543Smrg
344706f2543Smrg    free(ke);
345706f2543Smrg    pi->driverPrivate = 0;
346706f2543Smrg}
347706f2543Smrg
348706f2543Smrgstatic void
349706f2543SmrgEvdevPtrFini (KdPointerInfo *pi)
350706f2543Smrg{
351706f2543Smrg}
352706f2543Smrg
353706f2543Smrg
354706f2543Smrg/*
355706f2543Smrg * Evdev keyboard functions
356706f2543Smrg */
357706f2543Smrg
358706f2543Smrgstatic void
359706f2543SmrgreadMapping (KdKeyboardInfo *ki)
360706f2543Smrg{
361706f2543Smrg    if (!ki)
362706f2543Smrg        return;
363706f2543Smrg
364706f2543Smrg    ki->minScanCode = 0;
365706f2543Smrg    ki->maxScanCode = 247;
366706f2543Smrg}
367706f2543Smrg
368706f2543Smrgstatic void
369706f2543SmrgEvdevKbdRead (int evdevPort, void *closure)
370706f2543Smrg{
371706f2543Smrg    KdKeyboardInfo	 *ki = closure;
372706f2543Smrg    struct input_event	 events[NUM_EVENTS];
373706f2543Smrg    int			 i, n;
374706f2543Smrg
375706f2543Smrg    n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
376706f2543Smrg    if (n <= 0) {
377706f2543Smrg        if (errno == ENODEV)
378706f2543Smrg            DeleteInputDeviceRequest(ki->dixdev);
379706f2543Smrg        return;
380706f2543Smrg    }
381706f2543Smrg
382706f2543Smrg    n /= sizeof (struct input_event);
383706f2543Smrg    for (i = 0; i < n; i++)
384706f2543Smrg    {
385706f2543Smrg        if (events[i].type == EV_KEY)
386706f2543Smrg	    KdEnqueueKeyboardEvent (ki, events[i].code, !events[i].value);
387706f2543Smrg/* FIXME: must implement other types of events
388706f2543Smrg        else
389706f2543Smrg            ErrorF("Event type (%d) not delivered\n", events[i].type);
390706f2543Smrg*/
391706f2543Smrg    }
392706f2543Smrg}
393706f2543Smrg
394706f2543Smrgstatic Status
395706f2543SmrgEvdevKbdInit (KdKeyboardInfo *ki)
396706f2543Smrg{
397706f2543Smrg    int fd;
398706f2543Smrg
399706f2543Smrg    if (!ki->path) {
400706f2543Smrg        ErrorF("Couldn't find evdev device path\n");
401706f2543Smrg        return BadValue;
402706f2543Smrg    }
403706f2543Smrg    else {
404706f2543Smrg        fd = open (ki->path, O_RDWR);
405706f2543Smrg        if (fd < 0) {
406706f2543Smrg            ErrorF("Failed to open evdev device %s\n", ki->path);
407706f2543Smrg            return BadMatch;
408706f2543Smrg        }
409706f2543Smrg    }
410706f2543Smrg
411706f2543Smrg    close (fd);
412706f2543Smrg
413706f2543Smrg    ki->name = strdup("Evdev keyboard");
414706f2543Smrg
415706f2543Smrg    readMapping(ki);
416706f2543Smrg
417706f2543Smrg    return Success;
418706f2543Smrg}
419706f2543Smrg
420706f2543Smrgstatic Status
421706f2543SmrgEvdevKbdEnable (KdKeyboardInfo *ki)
422706f2543Smrg{
423706f2543Smrg    unsigned long       ev[NBITS(EV_MAX)];
424706f2543Smrg    Kevdev              *ke;
425706f2543Smrg    int                 fd;
426706f2543Smrg
427706f2543Smrg    if (!ki || !ki->path)
428706f2543Smrg        return BadImplementation;
429706f2543Smrg
430706f2543Smrg    fd = open(ki->path, O_RDWR);
431706f2543Smrg    if (fd < 0)
432706f2543Smrg        return BadMatch;
433706f2543Smrg
434706f2543Smrg    if (ioctl (fd, EVIOCGRAB, 1) < 0)
435706f2543Smrg        perror ("Grabbing evdev keyboard device failed");
436706f2543Smrg
437706f2543Smrg    if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) {
438706f2543Smrg        perror ("EVIOCGBIT 0");
439706f2543Smrg        close (fd);
440706f2543Smrg        return BadMatch;
441706f2543Smrg    }
442706f2543Smrg
443706f2543Smrg    ke = calloc(1, sizeof (Kevdev));
444706f2543Smrg    if (!ke) {
445706f2543Smrg        close (fd);
446706f2543Smrg        return BadAlloc;
447706f2543Smrg    }
448706f2543Smrg
449706f2543Smrg    if (!KdRegisterFd (fd, EvdevKbdRead, ki)) {
450706f2543Smrg        free(ke);
451706f2543Smrg        close (fd);
452706f2543Smrg        return BadAlloc;
453706f2543Smrg    }
454706f2543Smrg    ki->driverPrivate = ke;
455706f2543Smrg    ke->fd = fd;
456706f2543Smrg
457706f2543Smrg    return Success;
458706f2543Smrg}
459706f2543Smrg
460706f2543Smrgstatic void
461706f2543SmrgEvdevKbdLeds (KdKeyboardInfo *ki, int leds)
462706f2543Smrg{
463706f2543Smrg/*    struct input_event event;
464706f2543Smrg    Kevdev             *ke;
465706f2543Smrg
466706f2543Smrg    ki->driverPrivate = ke;
467706f2543Smrg
468706f2543Smrg    memset(&event, 0, sizeof(event));
469706f2543Smrg
470706f2543Smrg    event.type = EV_LED;
471706f2543Smrg    event.code = LED_CAPSL;
472706f2543Smrg    event.value = leds & (1 << 0) ? 1 : 0;
473706f2543Smrg    write(ke->fd, (char *) &event, sizeof(event));
474706f2543Smrg
475706f2543Smrg    event.type = EV_LED;
476706f2543Smrg    event.code = LED_NUML;
477706f2543Smrg    event.value = leds & (1 << 1) ? 1 : 0;
478706f2543Smrg    write(ke->fd, (char *) &event, sizeof(event));
479706f2543Smrg
480706f2543Smrg    event.type = EV_LED;
481706f2543Smrg    event.code = LED_SCROLLL;
482706f2543Smrg    event.value = leds & (1 << 2) ? 1 : 0;
483706f2543Smrg    write(ke->fd, (char *) &event, sizeof(event));
484706f2543Smrg
485706f2543Smrg    event.type = EV_LED;
486706f2543Smrg    event.code = LED_COMPOSE;
487706f2543Smrg    event.value = leds & (1 << 3) ? 1 : 0;
488706f2543Smrg    write(ke->fd, (char *) &event, sizeof(event));
489706f2543Smrg*/
490706f2543Smrg}
491706f2543Smrg
492706f2543Smrgstatic void
493706f2543SmrgEvdevKbdBell (KdKeyboardInfo *ki, int volume, int frequency, int duration)
494706f2543Smrg{
495706f2543Smrg}
496706f2543Smrg
497706f2543Smrgstatic void
498706f2543SmrgEvdevKbdDisable (KdKeyboardInfo *ki)
499706f2543Smrg{
500706f2543Smrg    Kevdev              *ke;
501706f2543Smrg
502706f2543Smrg    ke = ki->driverPrivate;
503706f2543Smrg
504706f2543Smrg    if (!ki || !ki->driverPrivate)
505706f2543Smrg        return;
506706f2543Smrg
507706f2543Smrg    KdUnregisterFd (ki, ke->fd, TRUE);
508706f2543Smrg
509706f2543Smrg    if (ioctl (ke->fd, EVIOCGRAB, 0) < 0)
510706f2543Smrg        perror ("Ungrabbing evdev keyboard device failed");
511706f2543Smrg
512706f2543Smrg    free(ke);
513706f2543Smrg    ki->driverPrivate = 0;
514706f2543Smrg}
515706f2543Smrg
516706f2543Smrgstatic void
517706f2543SmrgEvdevKbdFini (KdKeyboardInfo *ki)
518706f2543Smrg{
519706f2543Smrg}
520706f2543Smrg
521706f2543SmrgKdPointerDriver LinuxEvdevMouseDriver = {
522706f2543Smrg    "evdev",
523706f2543Smrg    EvdevPtrInit,
524706f2543Smrg    EvdevPtrEnable,
525706f2543Smrg    EvdevPtrDisable,
526706f2543Smrg    EvdevPtrFini,
527706f2543Smrg    NULL,
528706f2543Smrg};
529706f2543Smrg
530706f2543SmrgKdKeyboardDriver LinuxEvdevKeyboardDriver = {
531706f2543Smrg    "evdev",
532706f2543Smrg    EvdevKbdInit,
533706f2543Smrg    EvdevKbdEnable,
534706f2543Smrg    EvdevKbdLeds,
535706f2543Smrg    EvdevKbdBell,
536706f2543Smrg    EvdevKbdDisable,
537706f2543Smrg    EvdevKbdFini,
538706f2543Smrg    NULL,
539706f2543Smrg};
540