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