1/*
2 * Copyright � 1999 Keith Packard
3 * Copyright � 2006 Nokia Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the authors not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  The authors make no
12 * representations about the suitability of this software for any purpose.  It
13 * is provided "as is" without express or implied warranty.
14 *
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <kdrive-config.h>
26#endif
27#include "kdrive.h"
28#include "inputstr.h"
29
30#define XK_PUBLISHING
31#include <X11/keysym.h>
32#if HAVE_X11_XF86KEYSYM_H
33#include <X11/XF86keysym.h>
34#endif
35#include <signal.h>
36#include <stdio.h>
37#ifdef sun
38#include <sys/file.h> /* needed for FNONBLOCK & FASYNC */
39#endif
40
41#include "xkbsrv.h"
42
43#include <X11/extensions/XI.h>
44#include <X11/extensions/XIproto.h>
45#include "XIstubs.h" /* even though we don't use stubs.  cute, no? */
46#include "exevents.h"
47#include "extinit.h"
48#include "exglobals.h"
49#include "eventstr.h"
50#include "xserver-properties.h"
51#include "inpututils.h"
52
53#define AtomFromName(x) MakeAtom(x, strlen(x), 1)
54
55struct KdConfigDevice {
56    char *line;
57    struct KdConfigDevice *next;
58};
59
60/* kdKeyboards and kdPointers hold all the real devices. */
61static KdKeyboardInfo *kdKeyboards         = NULL;
62static KdPointerInfo  *kdPointers          = NULL;
63static struct KdConfigDevice *kdConfigKeyboards   = NULL;
64static struct KdConfigDevice *kdConfigPointers    = NULL;
65
66static KdKeyboardDriver *kdKeyboardDrivers = NULL;
67static KdPointerDriver  *kdPointerDrivers  = NULL;
68
69static EventListPtr     kdEvents = NULL;
70
71static Bool		kdInputEnabled;
72static Bool		kdOffScreen;
73static unsigned long	kdOffScreenTime;
74static KdPointerMatrix	kdPointerMatrix = {
75   { { 1, 0, 0 },
76     { 0, 1, 0 } }
77};
78
79void KdResetInputMachine (void);
80
81#define KD_MAX_INPUT_FDS    8
82
83typedef struct _kdInputFd {
84    int	        fd;
85    void        (*read) (int fd, void *closure);
86    int	        (*enable) (int fd, void *closure);
87    void        (*disable) (int fd, void *closure);
88    void        *closure;
89} KdInputFd;
90
91static KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
92static int	 kdNumInputFds;
93
94extern Bool      kdRawPointerCoordinates;
95
96static void
97KdSigio (int sig)
98{
99    int	i;
100
101    for (i = 0; i < kdNumInputFds; i++)
102	(*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
103}
104
105static void
106KdBlockSigio (void)
107{
108    sigset_t	set;
109
110    sigemptyset (&set);
111    sigaddset (&set, SIGIO);
112    sigprocmask (SIG_BLOCK, &set, 0);
113}
114
115static void
116KdUnblockSigio (void)
117{
118    sigset_t	set;
119
120    sigemptyset (&set);
121    sigaddset (&set, SIGIO);
122    sigprocmask (SIG_UNBLOCK, &set, 0);
123}
124
125#ifdef DEBUG_SIGIO
126
127void
128KdAssertSigioBlocked (char *where)
129{
130    sigset_t	set, old;
131
132    sigemptyset (&set);
133    sigprocmask (SIG_BLOCK, &set, &old);
134    if (!sigismember (&old, SIGIO)) {
135	ErrorF ("SIGIO not blocked at %s\n", where);
136        KdBacktrace(0);
137    }
138}
139
140#else
141
142#define KdAssertSigioBlocked(s)
143
144#endif
145
146static int  kdnFds;
147
148#ifdef FNONBLOCK
149#define NOBLOCK FNONBLOCK
150#else
151#define NOBLOCK FNDELAY
152#endif
153
154void
155KdResetInputMachine (void)
156{
157    KdPointerInfo *pi;
158
159    for (pi = kdPointers; pi; pi = pi->next) {
160        pi->mouseState = start;
161        pi->eventHeld = FALSE;
162    }
163}
164
165static void
166KdNonBlockFd (int fd)
167{
168    int	flags;
169    flags = fcntl (fd, F_GETFL);
170    flags |= FASYNC|NOBLOCK;
171    fcntl (fd, F_SETFL, flags);
172}
173
174static void
175KdAddFd (int fd)
176{
177    struct sigaction	act;
178    sigset_t		set;
179
180    kdnFds++;
181    fcntl (fd, F_SETOWN, getpid());
182    KdNonBlockFd (fd);
183    AddEnabledDevice (fd);
184    memset (&act, '\0', sizeof act);
185    act.sa_handler = KdSigio;
186    sigemptyset (&act.sa_mask);
187    sigaddset (&act.sa_mask, SIGIO);
188    sigaddset (&act.sa_mask, SIGALRM);
189    sigaddset (&act.sa_mask, SIGVTALRM);
190    sigaction (SIGIO, &act, 0);
191    sigemptyset (&set);
192    sigprocmask (SIG_SETMASK, &set, 0);
193}
194
195static void
196KdRemoveFd (int fd)
197{
198    struct sigaction	act;
199    int			flags;
200
201    kdnFds--;
202    RemoveEnabledDevice (fd);
203    flags = fcntl (fd, F_GETFL);
204    flags &= ~(FASYNC|NOBLOCK);
205    fcntl (fd, F_SETFL, flags);
206    if (kdnFds == 0)
207    {
208	memset (&act, '\0', sizeof act);
209	act.sa_handler = SIG_IGN;
210	sigemptyset (&act.sa_mask);
211	sigaction (SIGIO, &act, 0);
212    }
213}
214
215Bool
216KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure)
217{
218    if (kdNumInputFds == KD_MAX_INPUT_FDS)
219	return FALSE;
220    kdInputFds[kdNumInputFds].fd = fd;
221    kdInputFds[kdNumInputFds].read = read;
222    kdInputFds[kdNumInputFds].enable = 0;
223    kdInputFds[kdNumInputFds].disable = 0;
224    kdInputFds[kdNumInputFds].closure = closure;
225    kdNumInputFds++;
226    if (kdInputEnabled)
227	KdAddFd (fd);
228    return TRUE;
229}
230
231void
232KdUnregisterFd (void *closure, int fd, Bool do_close)
233{
234    int	i, j;
235
236    for (i = 0; i < kdNumInputFds; i++) {
237	if (kdInputFds[i].closure == closure &&
238            (fd == -1 || kdInputFds[i].fd == fd)) {
239	    if (kdInputEnabled)
240		KdRemoveFd (kdInputFds[i].fd);
241	    if (do_close)
242		close (kdInputFds[i].fd);
243	    kdNumInputFds--;
244	    for (j = i; j < kdNumInputFds; j++)
245		kdInputFds[j] = kdInputFds[j+1];
246            break;
247	}
248    }
249}
250
251void
252KdUnregisterFds (void *closure, Bool do_close)
253{
254    KdUnregisterFd(closure, -1, do_close);
255}
256
257void
258KdDisableInput (void)
259{
260    KdKeyboardInfo *ki;
261    KdPointerInfo *pi;
262    int found = 0, i = 0;
263
264    KdBlockSigio();
265
266    for (ki = kdKeyboards; ki; ki = ki->next) {
267        if (ki->driver && ki->driver->Disable)
268            (*ki->driver->Disable) (ki);
269    }
270
271    for (pi = kdPointers; pi; pi = pi->next) {
272        if (pi->driver && pi->driver->Disable)
273            (*pi->driver->Disable) (pi);
274    }
275
276    if (kdNumInputFds) {
277        ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!",
278               kdNumInputFds);
279        i = 0;
280        while (i < kdNumInputFds) {
281            found = 0;
282            for (ki = kdKeyboards; ki; ki = ki->next) {
283                if (ki == kdInputFds[i].closure) {
284                    ErrorF("    fd %d belongs to keybd driver %s\n",
285                           kdInputFds[i].fd,
286                           ki->driver && ki->driver->name ?
287                             ki->driver->name : "(unnamed!)");
288                    found = 1;
289                    break;
290                }
291            }
292
293            if (found) {
294                i++;
295                continue;
296            }
297
298            for (pi = kdPointers; pi; pi = pi->next) {
299                if (pi == kdInputFds[i].closure) {
300                    ErrorF("    fd %d belongs to pointer driver %s\n",
301                           kdInputFds[i].fd,
302                           pi->driver && pi->driver->name ?
303                             pi->driver->name : "(unnamed!)");
304                    break;
305                }
306            }
307
308            if (found) {
309                i++;
310                continue;
311            }
312
313            ErrorF("    fd %d not claimed by any active device!\n",
314                   kdInputFds[i].fd);
315            KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE);
316        }
317    }
318
319    kdInputEnabled = FALSE;
320}
321
322void
323KdEnableInput (void)
324{
325    InternalEvent ev;
326    KdKeyboardInfo *ki;
327    KdPointerInfo *pi;
328
329    kdInputEnabled = TRUE;
330
331    for (ki = kdKeyboards; ki; ki = ki->next) {
332        if (ki->driver && ki->driver->Enable)
333            (*ki->driver->Enable) (ki);
334    }
335
336    for (pi = kdPointers; pi; pi = pi->next) {
337        if (pi->driver && pi->driver->Enable)
338            (*pi->driver->Enable) (pi);
339    }
340
341    /* reset screen saver */
342    ev.any.time = GetTimeInMillis ();
343    NoticeEventTime (&ev);
344
345    KdUnblockSigio ();
346}
347
348static KdKeyboardDriver *
349KdFindKeyboardDriver (char *name)
350{
351    KdKeyboardDriver *ret;
352
353    /* ask a stupid question ... */
354    if (!name)
355        return NULL;
356
357    for (ret = kdKeyboardDrivers; ret; ret = ret->next) {
358        if (strcmp(ret->name, name) == 0)
359            return ret;
360    }
361
362    return NULL;
363}
364
365static KdPointerDriver *
366KdFindPointerDriver (char *name)
367{
368    KdPointerDriver *ret;
369
370    /* ask a stupid question ... */
371    if (!name)
372        return NULL;
373
374    for (ret = kdPointerDrivers; ret; ret = ret->next) {
375        if (strcmp(ret->name, name) == 0)
376            return ret;
377    }
378
379    return NULL;
380}
381
382static int
383KdPointerProc(DeviceIntPtr pDevice, int onoff)
384{
385    DevicePtr       pDev = (DevicePtr)pDevice;
386    KdPointerInfo   *pi;
387    Atom            xiclass;
388    Atom            *btn_labels;
389    Atom            *axes_labels;
390
391    if (!pDev)
392	return BadImplementation;
393
394    for (pi = kdPointers; pi; pi = pi->next) {
395        if (pi->dixdev && pi->dixdev->id == pDevice->id)
396            break;
397    }
398
399    if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) {
400        ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n",
401               pDevice->id);
402        return BadImplementation;
403    }
404
405    switch (onoff)
406    {
407    case DEVICE_INIT:
408#ifdef DEBUG
409        ErrorF("initialising pointer %s ...\n", pi->name);
410#endif
411        if (!pi->driver) {
412            if (!pi->driverPrivate) {
413                ErrorF("no driver specified for %s\n", pi->name);
414                return BadImplementation;
415            }
416
417            pi->driver = KdFindPointerDriver(pi->driverPrivate);
418            if (!pi->driver) {
419                ErrorF("Couldn't find pointer driver %s\n",
420                       pi->driverPrivate ? (char *) pi->driverPrivate :
421                       "(unnamed)");
422                return !Success;
423            }
424            free(pi->driverPrivate);
425            pi->driverPrivate = NULL;
426        }
427
428        if (!pi->driver->Init) {
429            ErrorF("no init function\n");
430            return BadImplementation;
431        }
432
433        if ((*pi->driver->Init) (pi) != Success) {
434            return !Success;
435        }
436
437	btn_labels = calloc(pi->nButtons, sizeof(Atom));
438	if (!btn_labels)
439	    return BadAlloc;
440	axes_labels = calloc(pi->nAxes, sizeof(Atom));
441	if (!axes_labels) {
442	    free(btn_labels);
443	    return BadAlloc;
444	}
445
446	switch(pi->nAxes)
447	{
448	    default:
449	    case 7:
450		btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
451	    case 6:
452		btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
453	    case 5:
454		btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
455	    case 4:
456		btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
457	    case 3:
458		btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
459	    case 2:
460		btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
461	    case 1:
462		btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
463	    case 0:
464		break;
465	}
466
467	if (pi->nAxes >= 2) {
468	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
469	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
470	}
471
472	InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels,
473	    (PtrCtrlProcPtr)NoopDDA,
474	    GetMotionHistorySize(), pi->nAxes, axes_labels);
475
476        free(btn_labels);
477        free(axes_labels);
478
479        if (pi->inputClass == KD_TOUCHSCREEN) {
480            InitAbsoluteClassDeviceStruct(pDevice);
481            xiclass = AtomFromName(XI_TOUCHSCREEN);
482        }
483        else {
484            xiclass = AtomFromName(XI_MOUSE);
485        }
486
487        AssignTypeAndName(pi->dixdev, xiclass,
488                          pi->name ? pi->name : "Generic KDrive Pointer");
489
490	return Success;
491
492    case DEVICE_ON:
493        if (pDev->on == TRUE)
494            return Success;
495
496        if (!pi->driver->Enable) {
497            ErrorF("no enable function\n");
498            return BadImplementation;
499        }
500
501        if ((*pi->driver->Enable) (pi) == Success) {
502            pDev->on = TRUE;
503            return Success;
504        }
505        else {
506            return BadImplementation;
507        }
508
509	return Success;
510
511    case DEVICE_OFF:
512        if (pDev->on == FALSE) {
513            return Success;
514        }
515
516        if (!pi->driver->Disable) {
517            return BadImplementation;
518        }
519        else {
520            (*pi->driver->Disable) (pi);
521            pDev->on = FALSE;
522            return Success;
523        }
524
525        return Success;
526
527    case DEVICE_CLOSE:
528	if (pDev->on) {
529            if (!pi->driver->Disable) {
530                return BadImplementation;
531            }
532            (*pi->driver->Disable) (pi);
533            pDev->on = FALSE;
534        }
535
536        if (!pi->driver->Fini)
537            return BadImplementation;
538
539        (*pi->driver->Fini) (pi);
540
541        KdRemovePointer(pi);
542
543        return Success;
544    }
545
546    /* NOTREACHED */
547    return BadImplementation;
548}
549
550Bool
551LegalModifier(unsigned int key, DeviceIntPtr pDev)
552{
553    return TRUE;
554}
555
556static void
557KdBell (int volume, DeviceIntPtr pDev, pointer arg, int something)
558{
559    KeybdCtrl *ctrl = arg;
560    KdKeyboardInfo *ki = NULL;
561
562    for (ki = kdKeyboards; ki; ki = ki->next) {
563        if (ki->dixdev && ki->dixdev->id == pDev->id)
564            break;
565    }
566
567    if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
568        return;
569
570    KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
571}
572
573void
574DDXRingBell(int volume, int pitch, int duration)
575{
576    KdKeyboardInfo *ki = NULL;
577
578    if (kdOsFuncs->Bell) {
579        (*kdOsFuncs->Bell)(volume, pitch, duration);
580    }
581    else {
582        for (ki = kdKeyboards; ki; ki = ki->next) {
583            if (ki->dixdev->coreEvents)
584                KdRingBell(ki, volume, pitch, duration);
585        }
586    }
587}
588
589void
590KdRingBell(KdKeyboardInfo *ki, int volume, int pitch, int duration)
591{
592    if (!ki || !ki->driver || !ki->driver->Bell)
593        return;
594
595    if (kdInputEnabled)
596        (*ki->driver->Bell) (ki, volume, pitch, duration);
597}
598
599
600static void
601KdSetLeds (KdKeyboardInfo *ki, int leds)
602{
603    if (!ki || !ki->driver)
604        return;
605
606    if (kdInputEnabled) {
607        if (ki->driver->Leds)
608            (*ki->driver->Leds) (ki, leds);
609    }
610}
611
612void
613KdSetLed (KdKeyboardInfo *ki, int led, Bool on)
614{
615    if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed)
616        return;
617
618    NoteLedState (ki->dixdev, led, on);
619    KdSetLeds (ki, ki->dixdev->kbdfeed->ctrl.leds);
620}
621
622void
623KdSetPointerMatrix (KdPointerMatrix *matrix)
624{
625    kdPointerMatrix = *matrix;
626}
627
628void
629KdComputePointerMatrix (KdPointerMatrix *m, Rotation randr, int width,
630                        int height)
631{
632    int		    x_dir = 1, y_dir = 1;
633    int		    i, j;
634    int		    size[2];
635
636    size[0] = width; size[1] = height;
637    if (randr & RR_Reflect_X)
638	x_dir = -1;
639    if (randr & RR_Reflect_Y)
640	y_dir = -1;
641    switch (randr & (RR_Rotate_All)) {
642    case RR_Rotate_0:
643	m->matrix[0][0] = x_dir; m->matrix[0][1] = 0;
644	m->matrix[1][0] = 0; m->matrix[1][1] = y_dir;
645	break;
646    case RR_Rotate_90:
647	m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir;
648	m->matrix[1][0] = y_dir; m->matrix[1][1] = 0;
649	break;
650    case RR_Rotate_180:
651	m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0;
652	m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir;
653	break;
654    case RR_Rotate_270:
655	m->matrix[0][0] = 0; m->matrix[0][1] = x_dir;
656	m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0;
657	break;
658    }
659    for (i = 0; i < 2; i++)
660    {
661	m->matrix[i][2] = 0;
662	for (j = 0 ; j < 2; j++)
663	    if (m->matrix[i][j] < 0)
664		m->matrix[i][2] = size[j] - 1;
665    }
666}
667
668void
669KdScreenToPointerCoords (int *x, int *y)
670{
671    int	(*m)[3] = kdPointerMatrix.matrix;
672    int div = m[0][1] * m[1][0] - m[1][1] * m[0][0];
673    int sx = *x;
674    int sy = *y;
675
676    *x = (m[0][1] * sy - m[0][1] * m[1][2] + m[1][1] * m[0][2] - m[1][1] * sx) / div;
677    *y = (m[1][0] * sx + m[0][0] * m[1][2] - m[1][0] * m[0][2] - m[0][0] * sy) / div;
678}
679
680static void
681KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
682{
683    KdKeyboardInfo *ki;
684
685    for (ki = kdKeyboards; ki; ki = ki->next) {
686        if (ki->dixdev && ki->dixdev->id == pDevice->id)
687            break;
688    }
689
690    if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
691        return;
692
693    KdSetLeds(ki, ctrl->leds);
694    ki->bellPitch = ctrl->bell_pitch;
695    ki->bellDuration = ctrl->bell_duration;
696}
697
698extern KeybdCtrl defaultKeyboardControl;
699
700static int
701KdKeyboardProc(DeviceIntPtr pDevice, int onoff)
702{
703    Bool        ret;
704    DevicePtr   pDev = (DevicePtr)pDevice;
705    KdKeyboardInfo *ki;
706    Atom xiclass;
707    XkbRMLVOSet rmlvo;
708
709    if (!pDev)
710	return BadImplementation;
711
712    for (ki = kdKeyboards; ki; ki = ki->next) {
713        if (ki->dixdev && ki->dixdev->id == pDevice->id)
714            break;
715    }
716
717    if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) {
718        return BadImplementation;
719    }
720
721    switch (onoff)
722    {
723    case DEVICE_INIT:
724#ifdef DEBUG
725        ErrorF("initialising keyboard %s\n", ki->name);
726#endif
727        if (!ki->driver) {
728            if (!ki->driverPrivate) {
729                ErrorF("no driver specified!\n");
730                return BadImplementation;
731            }
732
733            ki->driver = KdFindKeyboardDriver(ki->driverPrivate);
734            if (!ki->driver) {
735                ErrorF("Couldn't find keyboard driver %s\n",
736                       ki->driverPrivate ? (char *) ki->driverPrivate :
737                       "(unnamed)");
738                return !Success;
739            }
740            free(ki->driverPrivate);
741            ki->driverPrivate = NULL;
742        }
743
744        if (!ki->driver->Init) {
745            ErrorF("Keyboard %s: no init function\n", ki->name);
746            return BadImplementation;
747        }
748
749        if ((*ki->driver->Init) (ki) != Success) {
750            return !Success;
751        }
752
753        memset(&rmlvo, 0, sizeof(rmlvo));
754        rmlvo.rules = ki->xkbRules;
755        rmlvo.model = ki->xkbModel;
756        rmlvo.layout = ki->xkbLayout;
757        rmlvo.variant = ki->xkbVariant;
758        rmlvo.options = ki->xkbOptions;
759        ret = InitKeyboardDeviceStruct (pDevice, &rmlvo, KdBell, KdKbdCtrl);
760	if (!ret) {
761            ErrorF("Couldn't initialise keyboard %s\n", ki->name);
762	    return BadImplementation;
763        }
764
765        xiclass = AtomFromName(XI_KEYBOARD);
766        AssignTypeAndName(pDevice, xiclass,
767                          ki->name ? ki->name : "Generic KDrive Keyboard");
768
769        KdResetInputMachine();
770
771        return Success;
772
773    case DEVICE_ON:
774        if (pDev->on == TRUE)
775            return Success;
776
777        if (!ki->driver->Enable)
778            return BadImplementation;
779
780        if ((*ki->driver->Enable) (ki) != Success) {
781            return BadMatch;
782        }
783
784        pDev->on = TRUE;
785        return Success;
786
787    case DEVICE_OFF:
788        if (pDev->on == FALSE)
789            return Success;
790
791        if (!ki->driver->Disable)
792            return BadImplementation;
793
794        (*ki->driver->Disable) (ki);
795        pDev->on = FALSE;
796
797        return Success;
798
799        break;
800
801    case DEVICE_CLOSE:
802	if (pDev->on) {
803            if (!ki->driver->Disable)
804                return BadImplementation;
805
806            (*ki->driver->Disable) (ki);
807            pDev->on = FALSE;
808	}
809
810        if (!ki->driver->Fini)
811            return BadImplementation;
812
813        (*ki->driver->Fini) (ki);
814
815        KdRemoveKeyboard(ki);
816
817        return Success;
818    }
819
820    /* NOTREACHED */
821    return BadImplementation;
822}
823
824void
825KdAddPointerDriver (KdPointerDriver *driver)
826{
827    KdPointerDriver **prev;
828
829    if (!driver)
830        return;
831
832    for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) {
833        if (*prev == driver)
834            return;
835    }
836    *prev = driver;
837}
838
839void
840KdRemovePointerDriver (KdPointerDriver *driver)
841{
842    KdPointerDriver *tmp;
843
844    if (!driver)
845        return;
846
847    /* FIXME remove all pointers using this driver */
848    for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) {
849        if (tmp->next == driver)
850            tmp->next = driver->next;
851    }
852    if (tmp == driver)
853        tmp = NULL;
854}
855
856void
857KdAddKeyboardDriver (KdKeyboardDriver *driver)
858{
859    KdKeyboardDriver **prev;
860
861    if (!driver)
862        return;
863
864    for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) {
865        if (*prev == driver)
866            return;
867    }
868    *prev = driver;
869}
870
871void
872KdRemoveKeyboardDriver (KdKeyboardDriver *driver)
873{
874    KdKeyboardDriver *tmp;
875
876    if (!driver)
877        return;
878
879    /* FIXME remove all keyboards using this driver */
880    for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) {
881        if (tmp->next == driver)
882            tmp->next = driver->next;
883    }
884    if (tmp == driver)
885        tmp = NULL;
886}
887
888KdKeyboardInfo *
889KdNewKeyboard (void)
890{
891    KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1);
892    if (!ki)
893        return NULL;
894
895    ki->minScanCode = 0;
896    ki->maxScanCode = 0;
897    ki->leds = 0;
898    ki->bellPitch = 1000;
899    ki->bellDuration = 200;
900    ki->next = NULL;
901    ki->options = NULL;
902    ki->xkbRules = strdup(XKB_DFLT_RULES);
903    ki->xkbModel = strdup(XKB_DFLT_MODEL);
904    ki->xkbLayout = strdup(XKB_DFLT_LAYOUT);
905    ki->xkbVariant = strdup(XKB_DFLT_VARIANT);
906    ki->xkbOptions = strdup(XKB_DFLT_OPTIONS);
907
908    return ki;
909}
910
911int
912KdAddConfigKeyboard (char *keyboard)
913{
914    struct KdConfigDevice **prev, *new;
915
916    if (!keyboard)
917        return Success;
918
919    new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
920    if (!new)
921        return BadAlloc;
922
923    new->line = strdup(keyboard);
924    new->next = NULL;
925
926    for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next);
927    *prev = new;
928
929    return Success;
930}
931
932int
933KdAddKeyboard (KdKeyboardInfo *ki)
934{
935    KdKeyboardInfo **prev;
936
937    if (!ki)
938        return !Success;
939
940    ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE);
941    if (!ki->dixdev) {
942        ErrorF("Couldn't register keyboard device %s\n",
943               ki->name ? ki->name : "(unnamed)");
944        return !Success;
945    }
946
947#ifdef DEBUG
948    ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id);
949#endif
950
951    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next);
952    *prev = ki;
953
954    return Success;
955}
956
957void
958KdRemoveKeyboard (KdKeyboardInfo *ki)
959{
960    KdKeyboardInfo **prev;
961
962    if (!ki)
963        return;
964
965    for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) {
966        if (*prev == ki) {
967            *prev = ki->next;
968            break;
969        }
970    }
971
972    KdFreeKeyboard(ki);
973}
974
975int
976KdAddConfigPointer (char *pointer)
977{
978    struct KdConfigDevice **prev, *new;
979
980    if (!pointer)
981        return Success;
982
983    new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
984    if (!new)
985        return BadAlloc;
986
987    new->line = strdup(pointer);
988    new->next = NULL;
989
990    for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
991    *prev = new;
992
993    return Success;
994}
995
996int
997KdAddPointer (KdPointerInfo *pi)
998{
999    KdPointerInfo **prev;
1000
1001    if (!pi)
1002        return Success;
1003
1004    pi->mouseState = start;
1005    pi->eventHeld = FALSE;
1006
1007    pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE);
1008    if (!pi->dixdev) {
1009        ErrorF("Couldn't add pointer device %s\n",
1010               pi->name ? pi->name : "(unnamed)");
1011        return BadDevice;
1012    }
1013
1014    for (prev = &kdPointers; *prev; prev = &(*prev)->next);
1015    *prev = pi;
1016
1017    return Success;
1018}
1019
1020void
1021KdRemovePointer (KdPointerInfo *pi)
1022{
1023    KdPointerInfo **prev;
1024
1025    if (!pi)
1026        return;
1027
1028    for (prev = &kdPointers; *prev; prev = &(*prev)->next) {
1029        if (*prev == pi) {
1030            *prev = pi->next;
1031            break;
1032        }
1033    }
1034
1035    KdFreePointer(pi);
1036}
1037
1038/*
1039 * You can call your kdriver server with something like:
1040 * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd
1041 * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br
1042 */
1043static Bool
1044KdGetOptions (InputOption **options, char *string)
1045{
1046    InputOption     *newopt = NULL, **tmpo = NULL;
1047    int             tam_key = 0;
1048
1049    newopt = calloc(1, sizeof (InputOption));
1050    if (!newopt)
1051        return FALSE;
1052
1053    for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next)
1054        ; /* Hello, I'm here */
1055    *tmpo = newopt;
1056
1057    if (strchr(string, '='))
1058    {
1059        tam_key = (strchr(string, '=') - string);
1060        newopt->key = (char *)malloc(tam_key);
1061        strncpy(newopt->key, string, tam_key);
1062        newopt->key[tam_key] = '\0';
1063        newopt->value = strdup(strchr(string, '=') + 1);
1064    }
1065    else
1066    {
1067        newopt->key = strdup(string);
1068        newopt->value = NULL;
1069    }
1070    newopt->next = NULL;
1071
1072    return TRUE;
1073}
1074
1075static void
1076KdParseKbdOptions (KdKeyboardInfo *ki)
1077{
1078    InputOption *option = NULL;
1079
1080    for (option = ki->options; option; option = option->next)
1081    {
1082        if (strcasecmp(option->key, "XkbRules") == 0)
1083            ki->xkbRules = option->value;
1084        else if (strcasecmp(option->key, "XkbModel") == 0)
1085            ki->xkbModel = option->value;
1086        else if (strcasecmp(option->key, "XkbLayout") == 0)
1087            ki->xkbLayout = option->value;
1088        else if (strcasecmp(option->key, "XkbVariant") == 0)
1089            ki->xkbVariant = option->value;
1090        else if (strcasecmp(option->key, "XkbOptions") == 0)
1091            ki->xkbOptions = option->value;
1092        else if (!strcasecmp (option->key, "device"))
1093            ki->path = strdup(option->value);
1094        else
1095           ErrorF("Kbd option key (%s) of value (%s) not assigned!\n",
1096                    option->key, option->value);
1097    }
1098}
1099
1100KdKeyboardInfo *
1101KdParseKeyboard (char *arg)
1102{
1103    char            save[1024];
1104    char            delim;
1105    InputOption     *options = NULL;
1106    KdKeyboardInfo     *ki = NULL;
1107
1108    ki = KdNewKeyboard();
1109    if (!ki)
1110        return NULL;
1111
1112    ki->name = strdup("Unknown KDrive Keyboard");
1113    ki->path = NULL;
1114    ki->driver = NULL;
1115    ki->driverPrivate = NULL;
1116    ki->next = NULL;
1117
1118    if (!arg)
1119    {
1120        ErrorF("keybd: no arg\n");
1121        KdFreeKeyboard (ki);
1122        return NULL;
1123    }
1124
1125    if (strlen (arg) >= sizeof (save))
1126    {
1127        ErrorF("keybd: arg too long\n");
1128        KdFreeKeyboard (ki);
1129        return NULL;
1130    }
1131
1132    arg = KdParseFindNext (arg, ",", save, &delim);
1133    if (!save[0])
1134    {
1135        ErrorF("keybd: failed on save[0]\n");
1136        KdFreeKeyboard (ki);
1137        return NULL;
1138    }
1139
1140    if (strcmp (save, "auto") == 0)
1141        ki->driverPrivate = NULL;
1142    else
1143        ki->driverPrivate = strdup(save);
1144
1145    if (delim != ',')
1146    {
1147        return ki;
1148    }
1149
1150    arg = KdParseFindNext (arg, ",", save, &delim);
1151
1152    while (delim == ',')
1153    {
1154        arg = KdParseFindNext (arg, ",", save, &delim);
1155
1156	if (!KdGetOptions(&options, save))
1157	{
1158	    KdFreeKeyboard(ki);
1159	    return NULL;
1160        }
1161    }
1162
1163    if (options)
1164    {
1165        ki->options = options;
1166        KdParseKbdOptions(ki);
1167    }
1168
1169    return ki;
1170}
1171
1172static void
1173KdParsePointerOptions (KdPointerInfo *pi)
1174{
1175    InputOption *option = NULL;
1176
1177    for (option = pi->options; option; option = option->next)
1178    {
1179        if (!strcmp (option->key, "emulatemiddle"))
1180            pi->emulateMiddleButton = TRUE;
1181        else if (!strcmp (option->key, "noemulatemiddle"))
1182            pi->emulateMiddleButton = FALSE;
1183        else if (!strcmp (option->key, "transformcoord"))
1184            pi->transformCoordinates = TRUE;
1185        else if (!strcmp (option->key, "rawcoord"))
1186            pi->transformCoordinates = FALSE;
1187        else if (!strcasecmp (option->key, "device"))
1188            pi->path = strdup(option->value);
1189        else if (!strcasecmp (option->key, "protocol"))
1190            pi->protocol = strdup(option->value);
1191        else
1192            ErrorF("Pointer option key (%s) of value (%s) not assigned!\n",
1193                    option->key, option->value);
1194    }
1195}
1196
1197KdPointerInfo *
1198KdParsePointer (char *arg)
1199{
1200    char            save[1024];
1201    char            delim;
1202    KdPointerInfo   *pi = NULL;
1203    InputOption     *options = NULL;
1204    int             i = 0;
1205
1206    pi = KdNewPointer();
1207    if (!pi)
1208        return NULL;
1209    pi->emulateMiddleButton = kdEmulateMiddleButton;
1210    pi->transformCoordinates = !kdRawPointerCoordinates;
1211    pi->protocol = NULL;
1212    pi->nButtons = 5; /* XXX should not be hardcoded */
1213    pi->inputClass = KD_MOUSE;
1214
1215    if (!arg)
1216    {
1217        ErrorF("mouse: no arg\n");
1218        KdFreePointer (pi);
1219        return NULL;
1220    }
1221
1222    if (strlen (arg) >= sizeof (save))
1223    {
1224        ErrorF("mouse: arg too long\n");
1225        KdFreePointer (pi);
1226        return NULL;
1227    }
1228    arg = KdParseFindNext (arg, ",", save, &delim);
1229    if (!save[0])
1230    {
1231        ErrorF("failed on save[0]\n");
1232        KdFreePointer (pi);
1233        return NULL;
1234    }
1235
1236    if (strcmp(save, "auto") == 0)
1237        pi->driverPrivate = NULL;
1238    else
1239        pi->driverPrivate = strdup(save);
1240
1241    if (delim != ',')
1242    {
1243        return pi;
1244    }
1245
1246    arg = KdParseFindNext (arg, ",", save, &delim);
1247
1248    while (delim == ',')
1249    {
1250        arg = KdParseFindNext (arg, ",", save, &delim);
1251        if (save[0] == '{')
1252        {
1253            char *s = save + 1;
1254             i = 0;
1255             while (*s && *s != '}')
1256             {
1257                if ('1' <= *s && *s <= '0' + pi->nButtons)
1258                    pi->map[i] = *s - '0';
1259                else
1260                    UseMsg ();
1261                s++;
1262             }
1263        }
1264        else
1265        {
1266            if (!KdGetOptions(&options, save))
1267            {
1268                KdFreePointer(pi);
1269                return NULL;
1270            }
1271        }
1272    }
1273
1274    if (options)
1275    {
1276        pi->options = options;
1277        KdParsePointerOptions(pi);
1278    }
1279
1280    return pi;
1281}
1282
1283
1284void
1285KdInitInput (void)
1286{
1287    KdPointerInfo *pi;
1288    KdKeyboardInfo *ki;
1289    struct KdConfigDevice *dev;
1290
1291    kdInputEnabled = TRUE;
1292
1293    for (dev = kdConfigPointers; dev; dev = dev->next) {
1294        pi = KdParsePointer(dev->line);
1295        if (!pi)
1296            ErrorF("Failed to parse pointer\n");
1297        if (KdAddPointer(pi) != Success)
1298            ErrorF("Failed to add pointer!\n");
1299    }
1300    for (dev = kdConfigKeyboards; dev; dev = dev->next) {
1301        ki = KdParseKeyboard(dev->line);
1302        if (!ki)
1303            ErrorF("Failed to parse keyboard\n");
1304        if (KdAddKeyboard(ki) != Success)
1305            ErrorF("Failed to add keyboard!\n");
1306    }
1307
1308    mieqInit();
1309}
1310
1311/*
1312 * Middle button emulation state machine
1313 *
1314 *  Possible transitions:
1315 *	Button 1 press	    v1
1316 *	Button 1 release    ^1
1317 *	Button 2 press	    v2
1318 *	Button 2 release    ^2
1319 *	Button 3 press	    v3
1320 *	Button 3 release    ^3
1321 *	Button other press  vo
1322 *	Button other release ^o
1323 *	Mouse motion	    <>
1324 *	Keyboard event	    k
1325 *	timeout		    ...
1326 *	outside box	    <->
1327 *
1328 *  States:
1329 *	start
1330 *	button_1_pend
1331 *	button_1_down
1332 *	button_2_down
1333 *	button_3_pend
1334 *	button_3_down
1335 *	synthetic_2_down_13
1336 *	synthetic_2_down_3
1337 *	synthetic_2_down_1
1338 *
1339 *  Transition diagram
1340 *
1341 *  start
1342 *	v1  -> (hold) (settimeout) button_1_pend
1343 *	^1  -> (deliver) start
1344 *	v2  -> (deliver) button_2_down
1345 *	^2  -> (deliever) start
1346 *	v3  -> (hold) (settimeout) button_3_pend
1347 *	^3  -> (deliver) start
1348 *	vo  -> (deliver) start
1349 *	^o  -> (deliver) start
1350 *	<>  -> (deliver) start
1351 *	k   -> (deliver) start
1352 *
1353 *  button_1_pend	(button 1 is down, timeout pending)
1354 *	^1  -> (release) (deliver) start
1355 *	v2  -> (release) (deliver) button_1_down
1356 *	^2  -> (release) (deliver) button_1_down
1357 *	v3  -> (cleartimeout) (generate v2) synthetic_2_down_13
1358 *	^3  -> (release) (deliver) button_1_down
1359 *	vo  -> (release) (deliver) button_1_down
1360 *	^o  -> (release) (deliver) button_1_down
1361 *	<-> -> (release) (deliver) button_1_down
1362 *	<>  -> (deliver) button_1_pend
1363 *	k   -> (release) (deliver) button_1_down
1364 *	... -> (release) button_1_down
1365 *
1366 *  button_1_down	(button 1 is down)
1367 *	^1  -> (deliver) start
1368 *	v2  -> (deliver) button_1_down
1369 *	^2  -> (deliver) button_1_down
1370 *	v3  -> (deliver) button_1_down
1371 *	^3  -> (deliver) button_1_down
1372 *	vo  -> (deliver) button_1_down
1373 *	^o  -> (deliver) button_1_down
1374 *	<>  -> (deliver) button_1_down
1375 *	k   -> (deliver) button_1_down
1376 *
1377 *  button_2_down	(button 2 is down)
1378 *	v1  -> (deliver) button_2_down
1379 *	^1  -> (deliver) button_2_down
1380 *	^2  -> (deliver) start
1381 *	v3  -> (deliver) button_2_down
1382 *	^3  -> (deliver) button_2_down
1383 *	vo  -> (deliver) button_2_down
1384 *	^o  -> (deliver) button_2_down
1385 *	<>  -> (deliver) button_2_down
1386 *	k   -> (deliver) button_2_down
1387 *
1388 *  button_3_pend	(button 3 is down, timeout pending)
1389 *	v1  -> (generate v2) synthetic_2_down
1390 *	^1  -> (release) (deliver) button_3_down
1391 *	v2  -> (release) (deliver) button_3_down
1392 *	^2  -> (release) (deliver) button_3_down
1393 *	^3  -> (release) (deliver) start
1394 *	vo  -> (release) (deliver) button_3_down
1395 *	^o  -> (release) (deliver) button_3_down
1396 *	<-> -> (release) (deliver) button_3_down
1397 *	<>  -> (deliver) button_3_pend
1398 *	k   -> (release) (deliver) button_3_down
1399 *	... -> (release) button_3_down
1400 *
1401 *  button_3_down	(button 3 is down)
1402 *	v1  -> (deliver) button_3_down
1403 *	^1  -> (deliver) button_3_down
1404 *	v2  -> (deliver) button_3_down
1405 *	^2  -> (deliver) button_3_down
1406 *	^3  -> (deliver) start
1407 *	vo  -> (deliver) button_3_down
1408 *	^o  -> (deliver) button_3_down
1409 *	<>  -> (deliver) button_3_down
1410 *	k   -> (deliver) button_3_down
1411 *
1412 *  synthetic_2_down_13	(button 1 and 3 are down)
1413 *	^1  -> (generate ^2) synthetic_2_down_3
1414 *	v2  -> synthetic_2_down_13
1415 *	^2  -> synthetic_2_down_13
1416 *	^3  -> (generate ^2) synthetic_2_down_1
1417 *	vo  -> (deliver) synthetic_2_down_13
1418 *	^o  -> (deliver) synthetic_2_down_13
1419 *	<>  -> (deliver) synthetic_2_down_13
1420 *	k   -> (deliver) synthetic_2_down_13
1421 *
1422 *  synthetic_2_down_3 (button 3 is down)
1423 *	v1  -> (deliver) synthetic_2_down_3
1424 *	^1  -> (deliver) synthetic_2_down_3
1425 *	v2  -> synthetic_2_down_3
1426 *	^2  -> synthetic_2_down_3
1427 *	^3  -> start
1428 *	vo  -> (deliver) synthetic_2_down_3
1429 *	^o  -> (deliver) synthetic_2_down_3
1430 *	<>  -> (deliver) synthetic_2_down_3
1431 *	k   -> (deliver) synthetic_2_down_3
1432 *
1433 *  synthetic_2_down_1 (button 1 is down)
1434 *	^1  -> start
1435 *	v2  -> synthetic_2_down_1
1436 *	^2  -> synthetic_2_down_1
1437 *	v3  -> (deliver) synthetic_2_down_1
1438 *	^3  -> (deliver) synthetic_2_down_1
1439 *	vo  -> (deliver) synthetic_2_down_1
1440 *	^o  -> (deliver) synthetic_2_down_1
1441 *	<>  -> (deliver) synthetic_2_down_1
1442 *	k   -> (deliver) synthetic_2_down_1
1443 */
1444
1445typedef enum _inputClass {
1446    down_1, up_1,
1447    down_2, up_2,
1448    down_3, up_3,
1449    down_o, up_o,
1450    motion, outside_box,
1451    keyboard, timeout,
1452    num_input_class
1453} KdInputClass;
1454
1455typedef enum _inputAction {
1456    noop,
1457    hold,
1458    setto,
1459    deliver,
1460    release,
1461    clearto,
1462    gen_down_2,
1463    gen_up_2
1464} KdInputAction;
1465
1466#define MAX_ACTIONS 2
1467
1468typedef struct _inputTransition {
1469    KdInputAction  actions[MAX_ACTIONS];
1470    KdPointerState nextState;
1471} KdInputTransition;
1472
1473static const
1474KdInputTransition  kdInputMachine[num_input_states][num_input_class] = {
1475    /* start */
1476    {
1477	{ { hold, setto },	    button_1_pend },	/* v1 */
1478	{ { deliver, noop },	    start },		/* ^1 */
1479	{ { deliver, noop },	    button_2_down },	/* v2 */
1480	{ { deliver, noop },	    start },		/* ^2 */
1481	{ { hold, setto },	    button_3_pend },	/* v3 */
1482	{ { deliver, noop },	    start },		/* ^3 */
1483	{ { deliver, noop },	    start },		/* vo */
1484	{ { deliver, noop },	    start },		/* ^o */
1485	{ { deliver, noop },	    start },		/* <> */
1486	{ { deliver, noop },	    start },		/* <-> */
1487	{ { noop, noop },	    start },		/* k */
1488	{ { noop, noop },	    start },		/* ... */
1489    },
1490    /* button_1_pend */
1491    {
1492	{ { noop, noop },	    button_1_pend },	/* v1 */
1493	{ { release, deliver },	    start },		/* ^1 */
1494	{ { release, deliver },	    button_1_down },	/* v2 */
1495	{ { release, deliver },	    button_1_down },	/* ^2 */
1496	{ { clearto, gen_down_2 },  synth_2_down_13 },	/* v3 */
1497	{ { release, deliver },	    button_1_down },	/* ^3 */
1498	{ { release, deliver },	    button_1_down },	/* vo */
1499	{ { release, deliver },	    button_1_down },	/* ^o */
1500	{ { deliver, noop },	    button_1_pend },	/* <> */
1501	{ { release, deliver },	    button_1_down },	/* <-> */
1502	{ { noop, noop },	    button_1_down },	/* k */
1503	{ { release, noop },	    button_1_down },	/* ... */
1504    },
1505    /* button_1_down */
1506    {
1507	{ { noop, noop },	    button_1_down },	/* v1 */
1508	{ { deliver, noop },	    start },		/* ^1 */
1509	{ { deliver, noop },	    button_1_down },	/* v2 */
1510	{ { deliver, noop },	    button_1_down },	/* ^2 */
1511	{ { deliver, noop },	    button_1_down },	/* v3 */
1512	{ { deliver, noop },	    button_1_down },	/* ^3 */
1513	{ { deliver, noop },	    button_1_down },	/* vo */
1514	{ { deliver, noop },	    button_1_down },	/* ^o */
1515	{ { deliver, noop },	    button_1_down },	/* <> */
1516	{ { deliver, noop },	    button_1_down },	/* <-> */
1517	{ { noop, noop },	    button_1_down },	/* k */
1518	{ { noop, noop },	    button_1_down },	/* ... */
1519    },
1520    /* button_2_down */
1521    {
1522	{ { deliver, noop },	    button_2_down },	/* v1 */
1523	{ { deliver, noop },	    button_2_down },	/* ^1 */
1524	{ { noop, noop },	    button_2_down },	/* v2 */
1525	{ { deliver, noop },	    start },		/* ^2 */
1526	{ { deliver, noop },	    button_2_down },	/* v3 */
1527	{ { deliver, noop },	    button_2_down },	/* ^3 */
1528	{ { deliver, noop },	    button_2_down },	/* vo */
1529	{ { deliver, noop },	    button_2_down },	/* ^o */
1530	{ { deliver, noop },	    button_2_down },	/* <> */
1531	{ { deliver, noop },	    button_2_down },	/* <-> */
1532	{ { noop, noop },	    button_2_down },	/* k */
1533	{ { noop, noop },	    button_2_down },	/* ... */
1534    },
1535    /* button_3_pend */
1536    {
1537	{ { clearto, gen_down_2 },  synth_2_down_13 },	/* v1 */
1538	{ { release, deliver },	    button_3_down },	/* ^1 */
1539	{ { release, deliver },	    button_3_down },	/* v2 */
1540	{ { release, deliver },	    button_3_down },	/* ^2 */
1541	{ { release, deliver },	    button_3_down },	/* v3 */
1542	{ { release, deliver },	    start },		/* ^3 */
1543	{ { release, deliver },	    button_3_down },	/* vo */
1544	{ { release, deliver },	    button_3_down },	/* ^o */
1545	{ { deliver, noop },	    button_3_pend },	/* <> */
1546	{ { release, deliver },	    button_3_down },	/* <-> */
1547	{ { release, noop },	    button_3_down },	/* k */
1548	{ { release, noop },	    button_3_down },	/* ... */
1549    },
1550    /* button_3_down */
1551    {
1552	{ { deliver, noop },	    button_3_down },	/* v1 */
1553	{ { deliver, noop },	    button_3_down },	/* ^1 */
1554	{ { deliver, noop },	    button_3_down },	/* v2 */
1555	{ { deliver, noop },	    button_3_down },	/* ^2 */
1556	{ { noop, noop },	    button_3_down },	/* v3 */
1557	{ { deliver, noop },	    start },		/* ^3 */
1558	{ { deliver, noop },	    button_3_down },	/* vo */
1559	{ { deliver, noop },	    button_3_down },	/* ^o */
1560	{ { deliver, noop },	    button_3_down },	/* <> */
1561	{ { deliver, noop },	    button_3_down },	/* <-> */
1562	{ { noop, noop },	    button_3_down },	/* k */
1563	{ { noop, noop },	    button_3_down },	/* ... */
1564    },
1565    /* synthetic_2_down_13 */
1566    {
1567	{ { noop, noop },	    synth_2_down_13 },	/* v1 */
1568	{ { gen_up_2, noop },	    synth_2_down_3 },	/* ^1 */
1569	{ { noop, noop },	    synth_2_down_13 },	/* v2 */
1570	{ { noop, noop },	    synth_2_down_13 },	/* ^2 */
1571	{ { noop, noop },	    synth_2_down_13 },	/* v3 */
1572	{ { gen_up_2, noop },	    synth_2_down_1 },	/* ^3 */
1573	{ { deliver, noop },	    synth_2_down_13 },	/* vo */
1574	{ { deliver, noop },	    synth_2_down_13 },	/* ^o */
1575	{ { deliver, noop },	    synth_2_down_13 },	/* <> */
1576	{ { deliver, noop },	    synth_2_down_13 },	/* <-> */
1577	{ { noop, noop },	    synth_2_down_13 },	/* k */
1578	{ { noop, noop },	    synth_2_down_13 },	/* ... */
1579    },
1580    /* synthetic_2_down_3 */
1581    {
1582	{ { deliver, noop },	    synth_2_down_3 },	/* v1 */
1583	{ { deliver, noop },	    synth_2_down_3 },	/* ^1 */
1584	{ { deliver, noop },	    synth_2_down_3 },	/* v2 */
1585	{ { deliver, noop },	    synth_2_down_3 },	/* ^2 */
1586	{ { noop, noop },	    synth_2_down_3 },	/* v3 */
1587	{ { noop, noop },	    start },		/* ^3 */
1588	{ { deliver, noop },	    synth_2_down_3 },	/* vo */
1589	{ { deliver, noop },	    synth_2_down_3 },	/* ^o */
1590	{ { deliver, noop },	    synth_2_down_3 },	/* <> */
1591	{ { deliver, noop },	    synth_2_down_3 },	/* <-> */
1592	{ { noop, noop },	    synth_2_down_3 },	/* k */
1593	{ { noop, noop },	    synth_2_down_3 },	/* ... */
1594    },
1595    /* synthetic_2_down_1 */
1596    {
1597	{ { noop, noop },	    synth_2_down_1 },	/* v1 */
1598	{ { noop, noop },	    start },		/* ^1 */
1599	{ { deliver, noop },	    synth_2_down_1 },	/* v2 */
1600	{ { deliver, noop },	    synth_2_down_1 },	/* ^2 */
1601	{ { deliver, noop },	    synth_2_down_1 },	/* v3 */
1602	{ { deliver, noop },	    synth_2_down_1 },	/* ^3 */
1603	{ { deliver, noop },	    synth_2_down_1 },	/* vo */
1604	{ { deliver, noop },	    synth_2_down_1 },	/* ^o */
1605	{ { deliver, noop },	    synth_2_down_1 },	/* <> */
1606	{ { deliver, noop },	    synth_2_down_1 },	/* <-> */
1607	{ { noop, noop },	    synth_2_down_1 },	/* k */
1608	{ { noop, noop },	    synth_2_down_1 },	/* ... */
1609    },
1610};
1611
1612#define EMULATION_WINDOW    10
1613#define EMULATION_TIMEOUT   100
1614
1615static int
1616KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z)
1617{
1618    pi->emulationDx = pi->heldEvent.x - x;
1619    pi->emulationDy = pi->heldEvent.y - y;
1620
1621    return (abs (pi->emulationDx) < EMULATION_WINDOW &&
1622	    abs (pi->emulationDy) < EMULATION_WINDOW);
1623}
1624
1625static KdInputClass
1626KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b)
1627{
1628    switch (type) {
1629    case ButtonPress:
1630	switch (b) {
1631	case 1: return down_1;
1632	case 2: return down_2;
1633	case 3: return down_3;
1634	default: return down_o;
1635	}
1636	break;
1637    case ButtonRelease:
1638	switch (b) {
1639	case 1: return up_1;
1640	case 2: return up_2;
1641	case 3: return up_3;
1642	default: return up_o;
1643	}
1644	break;
1645    case MotionNotify:
1646	if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z))
1647	    return outside_box;
1648	else
1649	    return motion;
1650    default:
1651	return keyboard;
1652    }
1653    return keyboard;
1654}
1655
1656#ifdef DEBUG
1657char	*kdStateNames[] = {
1658    "start",
1659    "button_1_pend",
1660    "button_1_down",
1661    "button_2_down",
1662    "button_3_pend",
1663    "button_3_down",
1664    "synth_2_down_13",
1665    "synth_2_down_3",
1666    "synthetic_2_down_1",
1667    "num_input_states"
1668};
1669
1670char	*kdClassNames[] = {
1671    "down_1", "up_1",
1672    "down_2", "up_2",
1673    "down_3", "up_3",
1674    "motion", "ouside_box",
1675    "keyboard", "timeout",
1676    "num_input_class"
1677};
1678
1679char *kdActionNames[] = {
1680    "noop",
1681    "hold",
1682    "setto",
1683    "deliver",
1684    "release",
1685    "clearto",
1686    "gen_down_2",
1687    "gen_up_2",
1688};
1689#endif /* DEBUG */
1690
1691static void
1692KdQueueEvent (DeviceIntPtr pDev, InternalEvent *ev)
1693{
1694    KdAssertSigioBlocked ("KdQueueEvent");
1695    mieqEnqueue (pDev, ev);
1696}
1697
1698/* We return true if we're stealing the event. */
1699static Bool
1700KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y,
1701                   int z, int b, int absrel)
1702{
1703    const KdInputTransition *t;
1704    int	a;
1705
1706    c = KdClassifyInput(pi, type, x, y, z, b);
1707    t = &kdInputMachine[pi->mouseState][c];
1708    for (a = 0; a < MAX_ACTIONS; a++)
1709    {
1710	switch (t->actions[a]) {
1711	case noop:
1712	    break;
1713	case hold:
1714	    pi->eventHeld = TRUE;
1715	    pi->emulationDx = 0;
1716	    pi->emulationDy = 0;
1717	    pi->heldEvent.type = type;
1718            pi->heldEvent.x = x;
1719            pi->heldEvent.y = y;
1720            pi->heldEvent.z = z;
1721            pi->heldEvent.flags = b;
1722            pi->heldEvent.absrel = absrel;
1723            return TRUE;
1724	    break;
1725	case setto:
1726	    pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
1727	    pi->timeoutPending = TRUE;
1728	    break;
1729	case deliver:
1730            _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1731                                    pi->heldEvent.y, pi->heldEvent.z,
1732                                    pi->heldEvent.flags, pi->heldEvent.absrel,
1733                                    TRUE);
1734	    break;
1735	case release:
1736	    pi->eventHeld = FALSE;
1737	    pi->timeoutPending = FALSE;
1738            _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x,
1739                                    pi->heldEvent.y, pi->heldEvent.z,
1740                                    pi->heldEvent.flags, pi->heldEvent.absrel,
1741                                    TRUE);
1742            return TRUE;
1743	    break;
1744	case clearto:
1745	    pi->timeoutPending = FALSE;
1746	    break;
1747	case gen_down_2:
1748            _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel,
1749                                    TRUE);
1750	    pi->eventHeld = FALSE;
1751            return TRUE;
1752	    break;
1753	case gen_up_2:
1754            _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel,
1755                                    TRUE);
1756            return TRUE;
1757	    break;
1758	}
1759    }
1760    pi->mouseState = t->nextState;
1761    return FALSE;
1762}
1763
1764static int
1765KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b,
1766                      int absrel)
1767{
1768    if (pi->emulateMiddleButton)
1769        return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b),
1770                                  type, x, y, z, b, absrel);
1771    return FALSE;
1772}
1773
1774static void
1775KdReceiveTimeout (KdPointerInfo *pi)
1776{
1777    KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0);
1778}
1779
1780/*
1781 * kdCheckTermination
1782 *
1783 * This function checks for the key sequence that terminates the server.  When
1784 * detected, it sets the dispatchException flag and returns.  The key sequence
1785 * is:
1786 *	Control-Alt
1787 * It's assumed that the server will be waken up by the caller when this
1788 * function returns.
1789 */
1790
1791extern int nClients;
1792
1793void
1794KdReleaseAllKeys (void)
1795{
1796#if 0
1797    int	key, nEvents, i;
1798    KdKeyboardInfo *ki;
1799
1800    KdBlockSigio ();
1801
1802    for (ki = kdKeyboards; ki; ki = ki->next) {
1803        for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode;
1804             key++) {
1805            if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) {
1806                KdHandleKeyboardEvent(ki, KeyRelease, key);
1807                GetEventList(&kdEvents);
1808                nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
1809                for (i = 0; i < nEvents; i++)
1810                    KdQueueEvent (ki->dixdev, (kdEvents + i)->event);
1811            }
1812        }
1813    }
1814
1815    KdUnblockSigio ();
1816#endif
1817}
1818
1819static void
1820KdCheckLock (void)
1821{
1822    KeyClassPtr	    keyc = NULL;
1823    Bool	    isSet = FALSE, shouldBeSet = FALSE;
1824    KdKeyboardInfo     *tmp = NULL;
1825
1826    for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
1827        if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
1828            keyc = tmp->dixdev->key;
1829            isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0;
1830            /* FIXME: Just use XKB indicators! */
1831            shouldBeSet = !!(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask);
1832            if (isSet != shouldBeSet)
1833                KdSetLed (tmp, tmp->LockLed, shouldBeSet);
1834        }
1835    }
1836}
1837
1838void
1839KdEnqueueKeyboardEvent(KdKeyboardInfo   *ki,
1840                       unsigned char scan_code,
1841		       unsigned char is_up)
1842{
1843    unsigned char key_code;
1844    KeyClassPtr	keyc = NULL;
1845    KeybdCtrl *ctrl = NULL;
1846    int type, nEvents, i;
1847
1848    if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
1849	return;
1850
1851    keyc = ki->dixdev->key;
1852    ctrl = &ki->dixdev->kbdfeed->ctrl;
1853
1854    if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode)
1855    {
1856	key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode;
1857
1858	/*
1859	 * Set up this event -- the type may be modified below
1860	 */
1861	if (is_up)
1862	    type = KeyRelease;
1863	else
1864	    type = KeyPress;
1865
1866        GetEventList(&kdEvents);
1867
1868        nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
1869        for (i = 0; i < nEvents; i++)
1870            KdQueueEvent(ki->dixdev, (InternalEvent *)((kdEvents + i)->event));
1871    }
1872    else {
1873        ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
1874               ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
1875    }
1876}
1877
1878/*
1879 * kdEnqueuePointerEvent
1880 *
1881 * This function converts hardware mouse event information into X event
1882 * information.  A mouse movement event is passed off to MI to generate
1883 * a MotionNotify event, if appropriate.  Button events are created and
1884 * passed off to MI for enqueueing.
1885 */
1886
1887/* FIXME do something a little more clever to deal with multiple axes here */
1888void
1889KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry,
1890                      int rz)
1891{
1892    CARD32        ms;
1893    unsigned char buttons;
1894    int           x, y, z;
1895    int           (*matrix)[3] = kdPointerMatrix.matrix;
1896    unsigned long button;
1897    int           n;
1898    int           dixflags = 0;
1899
1900    if (!pi)
1901	return;
1902
1903    ms = GetTimeInMillis();
1904
1905    /* we don't need to transform z, so we don't. */
1906    if (flags & KD_MOUSE_DELTA) {
1907	if (pi->transformCoordinates) {
1908	    x = matrix[0][0] * rx + matrix[0][1] * ry;
1909	    y = matrix[1][0] * rx + matrix[1][1] * ry;
1910	}
1911	else {
1912	    x = rx;
1913	    y = ry;
1914	}
1915    }
1916    else {
1917	if (pi->transformCoordinates) {
1918	    x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2];
1919	    y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2];
1920	}
1921	else {
1922	    x = rx;
1923	    y = ry;
1924	}
1925    }
1926    z = rz;
1927
1928    if (flags & KD_MOUSE_DELTA)
1929    {
1930        if (x || y || z)
1931        {
1932            dixflags = POINTER_RELATIVE | POINTER_ACCELERATE;
1933            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
1934        }
1935    } else
1936    {
1937        dixflags = POINTER_ABSOLUTE;
1938        if (x != pi->dixdev->last.valuators[0] ||
1939            y != pi->dixdev->last.valuators[1])
1940            _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE);
1941    }
1942
1943    buttons = flags;
1944
1945    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
1946         button <<= 1, n++) {
1947        if (((pi->buttonState & button) ^ (buttons & button)) &&
1948           !(buttons & button)) {
1949            _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n,
1950                                   dixflags, FALSE);
1951	}
1952    }
1953    for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons;
1954         button <<= 1, n++) {
1955	if (((pi->buttonState & button) ^ (buttons & button)) &&
1956	    (buttons & button)) {
1957            _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n,
1958                                   dixflags, FALSE);
1959        }
1960    }
1961
1962    pi->buttonState = buttons;
1963}
1964
1965void
1966_KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
1967                        int b, int absrel, Bool force)
1968{
1969    int nEvents = 0, i = 0;
1970    int valuators[3] = { x, y, z };
1971    ValuatorMask mask;
1972
1973    /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
1974    if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
1975        return;
1976
1977    valuator_mask_set_range(&mask, 0, 3, valuators);
1978
1979    GetEventList(&kdEvents);
1980    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, &mask);
1981    for (i = 0; i < nEvents; i++)
1982        KdQueueEvent(pi->dixdev, (InternalEvent *)((kdEvents + i)->event));
1983}
1984
1985void
1986KdBlockHandler (int		screen,
1987		pointer		blockData,
1988		pointer		timeout,
1989		pointer		readmask)
1990{
1991    KdPointerInfo		    *pi;
1992    int myTimeout=0;
1993
1994    for (pi = kdPointers; pi; pi = pi->next)
1995    {
1996	if (pi->timeoutPending)
1997	{
1998	    int	ms;
1999
2000	    ms = pi->emulationTimeout - GetTimeInMillis ();
2001	    if (ms < 1)
2002		ms = 1;
2003	    if(ms<myTimeout || myTimeout==0)
2004		    myTimeout=ms;
2005	}
2006    }
2007    /* if we need to poll for events, do that */
2008    if(kdOsFuncs->pollEvents)
2009    {
2010	    (*kdOsFuncs->pollEvents)();
2011	    myTimeout=20;
2012    }
2013    if(myTimeout>0)
2014    	AdjustWaitForDelay (timeout, myTimeout);
2015}
2016
2017void
2018KdWakeupHandler (int		screen,
2019		 pointer    	data,
2020		 unsigned long	lresult,
2021		 pointer	readmask)
2022{
2023    int		result = (int) lresult;
2024    fd_set	*pReadmask = (fd_set *) readmask;
2025    int		i;
2026    KdPointerInfo	*pi;
2027
2028    if (kdInputEnabled && result > 0)
2029    {
2030	for (i = 0; i < kdNumInputFds; i++)
2031	    if (FD_ISSET (kdInputFds[i].fd, pReadmask))
2032	    {
2033		KdBlockSigio ();
2034		(*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
2035		KdUnblockSigio ();
2036	    }
2037    }
2038    for (pi = kdPointers; pi; pi = pi->next)
2039    {
2040	if (pi->timeoutPending)
2041	{
2042	    if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0)
2043	    {
2044		pi->timeoutPending = FALSE;
2045		KdBlockSigio ();
2046		KdReceiveTimeout (pi);
2047		KdUnblockSigio ();
2048	    }
2049	}
2050    }
2051    if (kdSwitchPending)
2052	KdProcessSwitch ();
2053}
2054
2055#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
2056
2057static Bool
2058KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
2059{
2060    ScreenPtr	pScreen  = *ppScreen;
2061    ScreenPtr	pNewScreen;
2062    int		n;
2063    int		dx, dy;
2064    int		best_x, best_y;
2065    int		n_best_x, n_best_y;
2066    CARD32	ms;
2067
2068    if (kdDisableZaphod || screenInfo.numScreens <= 1)
2069	return FALSE;
2070
2071    if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
2072	return FALSE;
2073
2074    ms = GetTimeInMillis ();
2075    if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
2076	return FALSE;
2077    kdOffScreen = TRUE;
2078    kdOffScreenTime = ms;
2079    n_best_x = -1;
2080    best_x = 32767;
2081    n_best_y = -1;
2082    best_y = 32767;
2083    for (n = 0; n < screenInfo.numScreens; n++)
2084    {
2085	pNewScreen = screenInfo.screens[n];
2086	if (pNewScreen == pScreen)
2087	    continue;
2088	dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
2089	dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
2090	if (*x < 0)
2091	{
2092	    if (dx <= 0 && -dx < best_x)
2093	    {
2094		best_x = -dx;
2095		n_best_x = n;
2096	    }
2097	}
2098	else if (*x >= pScreen->width)
2099	{
2100	    if (dx >= 0 && dx < best_x)
2101	    {
2102		best_x = dx;
2103		n_best_x = n;
2104	    }
2105	}
2106	if (*y < 0)
2107	{
2108	    if (dy <= 0 && -dy < best_y)
2109	    {
2110		best_y = -dy;
2111		n_best_y = n;
2112	    }
2113	}
2114	else if (*y >= pScreen->height)
2115	{
2116	    if (dy >= 0 && dy < best_y)
2117	    {
2118		best_y = dy;
2119		n_best_y = n;
2120	    }
2121	}
2122    }
2123    if (best_y < best_x)
2124	n_best_x = n_best_y;
2125    if (n_best_x == -1)
2126	return FALSE;
2127    pNewScreen = screenInfo.screens[n_best_x];
2128
2129    if (*x < 0)
2130	*x += pNewScreen->width;
2131    if (*y < 0)
2132	*y += pNewScreen->height;
2133
2134    if (*x >= pScreen->width)
2135	*x -= pScreen->width;
2136    if (*y >= pScreen->height)
2137	*y -= pScreen->height;
2138
2139    *ppScreen = pNewScreen;
2140    return TRUE;
2141}
2142
2143static void
2144KdCrossScreen(ScreenPtr pScreen, Bool entering)
2145{
2146}
2147
2148int KdCurScreen;	/* current event screen */
2149
2150static void
2151KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
2152{
2153    KdBlockSigio ();
2154    KdCurScreen = pScreen->myNum;
2155    miPointerWarpCursor(pDev, pScreen, x, y);
2156    KdUnblockSigio ();
2157}
2158
2159miPointerScreenFuncRec kdPointerScreenFuncs =
2160{
2161    KdCursorOffScreen,
2162    KdCrossScreen,
2163    KdWarpCursor
2164};
2165
2166void
2167ProcessInputEvents (void)
2168{
2169    mieqProcessInputEvents();
2170    miPointerUpdateSprite(inputInfo.pointer);
2171    if (kdSwitchPending)
2172	KdProcessSwitch ();
2173    KdCheckLock ();
2174}
2175
2176/* At the moment, absolute/relative is up to the client. */
2177int
2178SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
2179{
2180    return BadMatch;
2181}
2182
2183int
2184SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
2185                   int *valuators, int first_valuator, int num_valuators)
2186{
2187    return BadMatch;
2188}
2189
2190int
2191ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
2192                        xDeviceCtl *control)
2193{
2194    switch (control->control) {
2195    case DEVICE_RESOLUTION:
2196        /* FIXME do something more intelligent here */
2197        return BadMatch;
2198
2199    case DEVICE_ABS_CALIB:
2200    case DEVICE_ABS_AREA:
2201        return Success;
2202
2203    case DEVICE_CORE:
2204        return BadMatch;
2205    case DEVICE_ENABLE:
2206        return Success;
2207
2208    default:
2209        return BadMatch;
2210    }
2211
2212    /* NOTREACHED */
2213    return BadImplementation;
2214}
2215
2216int
2217NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
2218                      DeviceIntPtr *pdev)
2219{
2220    InputOption *option = NULL;
2221    KdPointerInfo *pi = NULL;
2222    KdKeyboardInfo *ki = NULL;
2223
2224    for (option = options; option; option = option->next) {
2225        if (strcmp(option->key, "type") == 0) {
2226            if (strcmp(option->value, "pointer") == 0) {
2227                pi = KdNewPointer();
2228                if (!pi)
2229                    return BadAlloc;
2230            }
2231            else if (strcmp(option->value, "keyboard") == 0) {
2232                ki = KdNewKeyboard();
2233                if (!ki)
2234                    return BadAlloc;
2235            }
2236            else {
2237                ErrorF("unrecognised device type!\n");
2238                return BadValue;
2239            }
2240        }
2241#ifdef CONFIG_HAL
2242        else if (strcmp(option->key, "_source") == 0 &&
2243                 strcmp(option->value, "server/hal") == 0)
2244        {
2245            ErrorF("Ignoring device from HAL.\n");
2246            return BadValue;
2247        }
2248#endif
2249#ifdef CONFIG_UDEV
2250        else if (strcmp(option->key, "_source") == 0 &&
2251                 strcmp(option->value, "server/udev") == 0)
2252        {
2253            ErrorF("Ignoring device from udev.\n");
2254            return BadValue;
2255        }
2256#endif
2257    }
2258
2259    if (!ki && !pi) {
2260        ErrorF("unrecognised device identifier!\n");
2261        return BadValue;
2262    }
2263
2264    /* FIXME: change this code below to use KdParseKbdOptions and
2265     * KdParsePointerOptions */
2266    for (option = options; option; option = option->next) {
2267        if (strcmp(option->key, "device") == 0) {
2268            if (pi && option->value)
2269                pi->path = strdup(option->value);
2270            else if (ki && option->value)
2271                ki->path = strdup(option->value);
2272        }
2273        else if (strcmp(option->key, "driver") == 0) {
2274            if (pi) {
2275                pi->driver = KdFindPointerDriver(option->value);
2276                if (!pi->driver) {
2277                    ErrorF("couldn't find driver!\n");
2278                    KdFreePointer(pi);
2279                    return BadValue;
2280                }
2281                pi->options = options;
2282            }
2283            else if (ki) {
2284                ki->driver = KdFindKeyboardDriver(option->value);
2285                if (!ki->driver) {
2286                    ErrorF("couldn't find driver!\n");
2287                    KdFreeKeyboard(ki);
2288                    return BadValue;
2289                }
2290                ki->options = options;
2291            }
2292        }
2293    }
2294
2295    if (pi) {
2296        if (KdAddPointer(pi) != Success ||
2297            ActivateDevice(pi->dixdev, TRUE) != Success ||
2298            EnableDevice(pi->dixdev, TRUE) != TRUE) {
2299            ErrorF("couldn't add or enable pointer\n");
2300            return BadImplementation;
2301        }
2302    }
2303    else if (ki) {
2304        if (KdAddKeyboard(ki) != Success ||
2305            ActivateDevice(ki->dixdev, TRUE) != Success ||
2306            EnableDevice(ki->dixdev, TRUE) != TRUE) {
2307            ErrorF("couldn't add or enable keyboard\n");
2308            return BadImplementation;
2309        }
2310    }
2311
2312    if (pi) {
2313        *pdev = pi->dixdev;
2314    } else if(ki) {
2315        *pdev = ki->dixdev;
2316    }
2317
2318    return Success;
2319}
2320
2321void
2322DeleteInputDeviceRequest(DeviceIntPtr pDev)
2323{
2324    RemoveDevice(pDev, TRUE);
2325}
2326