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