Bug Summary

File:hw/kdrive/src/kinput.c
Location:line 1282, column 5
Description:Potential leak of memory pointed to by 'ki'

Annotated Source Code

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_H1
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) 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((void*)0);
63static KdPointerInfo *kdPointers = NULL((void*)0);
64static struct KdConfigDevice *kdConfigKeyboards = NULL((void*)0);
65static struct KdConfigDevice *kdConfigPointers = NULL((void*)0);
66
67static KdKeyboardDriver *kdKeyboardDrivers = NULL((void*)0);
68static KdPointerDriver *kdPointerDrivers = NULL((void*)0);
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_FDS8 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_FDS8];
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)(*(&set) = 0, 0);
113 sigprocmask(SIG_BLOCK1, &set, &old);
114 if (!sigismember(&old, SIGIO)((*(&old) & __sigbits(23)) != 0)) {
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 FNONBLOCK0x0004
129#define NOBLOCK0x0004 FNONBLOCK0x0004
130#else
131#define NOBLOCK0x0004 FNDELAY0x0004
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 = FALSE0;
142 }
143}
144
145static void
146KdNonBlockFd(int fd)
147{
148 int flags;
149
150 flags = fcntl(fd, F_GETFL3);
151 flags |= FASYNC0x0040 | NOBLOCK0x0004;
152 fcntl(fd, F_SETFL4, flags);
153}
154
155static void
156KdAddFd(int fd)
157{
158 struct sigaction act;
159 sigset_t set;
160
161 kdnFds++;
162 fcntl(fd, F_SETOWN6, getpid());
163 KdNonBlockFd(fd);
164 AddEnabledDevice(fd);
165 memset(&act, '\0', sizeof act)__builtin___memset_chk (&act, '\0', sizeof act, __builtin_object_size
(&act, 0))
;
166 act.sa_handler__sigaction_u.__sa_handler = KdSigio;
167 sigemptyset(&act.sa_mask)(*(&act.sa_mask) = 0, 0);
168 sigaddset(&act.sa_mask, SIGIO)(*(&act.sa_mask) |= __sigbits(23), 0);
169 sigaddset(&act.sa_mask, SIGALRM)(*(&act.sa_mask) |= __sigbits(14), 0);
170 sigaddset(&act.sa_mask, SIGVTALRM)(*(&act.sa_mask) |= __sigbits(26), 0);
171 sigaction(SIGIO23, &act, 0);
172 sigemptyset(&set)(*(&set) = 0, 0);
173 sigprocmask(SIG_SETMASK3, &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_GETFL3);
185 flags &= ~(FASYNC0x0040 | NOBLOCK0x0004);
186 fcntl(fd, F_SETFL4, flags);
187 if (kdnFds == 0) {
188 memset(&act, '\0', sizeof act)__builtin___memset_chk (&act, '\0', sizeof act, __builtin_object_size
(&act, 0))
;
189 act.sa_handler__sigaction_u.__sa_handler = SIG_IGN(void (*)(int))1;
190 sigemptyset(&act.sa_mask)(*(&act.sa_mask) = 0, 0);
191 sigaction(SIGIO23, &act, 0);
192 }
193}
194
195Bool
196KdRegisterFd(int fd, void (*read) (int fd, void *closure), void *closure)
197{
198 if (kdNumInputFds == KD_MAX_INPUT_FDS8)
199 return FALSE0;
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 TRUE1;
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 for (j = i; j < (kdNumInputFds - 1); j++)
224 kdInputFds[j] = kdInputFds[j + 1];
225 kdNumInputFds--;
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, TRUE1);
296 }
297 }
298
299 kdInputEnabled = FALSE0;
300}
301
302void
303KdEnableInput(void)
304{
305 InternalEvent ev;
306 KdKeyboardInfo *ki;
307 KdPointerInfo *pi;
308
309 kdInputEnabled = TRUE1;
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((void*)0);
338
339 for (ret = kdKeyboardDrivers; ret; ret = ret->next) {
340 if (strcmp(ret->name, name) == 0)
341 return ret;
342 }
343
344 return NULL((void*)0);
345}
346
347static KdPointerDriver *
348KdFindPointerDriver(const char *name)
349{
350 KdPointerDriver *ret;
351
352 /* ask a stupid question ... */
353 if (!name)
354 return NULL((void*)0);
355
356 for (ret = kdPointerDrivers; ret; ret = ret->next) {
357 if (strcmp(ret->name, name) == 0)
358 return ret;
359 }
360
361 return NULL((void*)0);
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 BadImplementation17;
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 BadImplementation17;
385 }
386
387 switch (onoff) {
388 case DEVICE_INIT0:
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 BadImplementation17;
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 !Success0;
404 }
405 free(pi->driverPrivate);
406 pi->driverPrivate = NULL((void*)0);
407 }
408
409 if (!pi->driver->Init) {
410 ErrorF("no init function\n");
411 return BadImplementation17;
412 }
413
414 if ((*pi->driver->Init) (pi) != Success0) {
415 return !Success0;
416 }
417
418 btn_labels = calloc(pi->nButtons, sizeof(Atom));
419 if (!btn_labels)
420 return BadAlloc11;
421 axes_labels = calloc(pi->nAxes, sizeof(Atom));
422 if (!axes_labels) {
423 free(btn_labels);
424 return BadAlloc11;
425 }
426
427 switch (pi->nAxes) {
428 default:
429 case 7:
430 btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT"Button Horiz Wheel Right");
431 case 6:
432 btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT"Button Horiz Wheel Left");
433 case 5:
434 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN"Button Wheel Down");
435 case 4:
436 btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP"Button Wheel Up");
437 case 3:
438 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT"Button Right");
439 case 2:
440 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE"Button Middle");
441 case 1:
442 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT"Button Left");
443 case 0:
444 break;
445 }
446
447 if (pi->nAxes >= 2) {
448 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X"Rel X");
449 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y"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_TOUCHSCREEN3) {
460 xiclass = AtomFromName(XI_TOUCHSCREEN)MakeAtom("TOUCHSCREEN", strlen("TOUCHSCREEN"), 1);
461 }
462 else {
463 xiclass = AtomFromName(XI_MOUSE)MakeAtom("MOUSE", strlen("MOUSE"), 1);
464 }
465
466 AssignTypeAndName(pi->dixdev, xiclass,
467 pi->name ? pi->name : "Generic KDrive Pointer");
468
469 return Success0;
470
471 case DEVICE_ON1:
472 if (pDev->on == TRUE1)
473 return Success0;
474
475 if (!pi->driver->Enable) {
476 ErrorF("no enable function\n");
477 return BadImplementation17;
478 }
479
480 if ((*pi->driver->Enable) (pi) == Success0) {
481 pDev->on = TRUE1;
482 return Success0;
483 }
484 else {
485 return BadImplementation17;
486 }
487
488 return Success0;
489
490 case DEVICE_OFF2:
491 if (pDev->on == FALSE0) {
492 return Success0;
493 }
494
495 if (!pi->driver->Disable) {
496 return BadImplementation17;
497 }
498 else {
499 (*pi->driver->Disable) (pi);
500 pDev->on = FALSE0;
501 return Success0;
502 }
503
504 return Success0;
505
506 case DEVICE_CLOSE3:
507 if (pDev->on) {
508 if (!pi->driver->Disable) {
509 return BadImplementation17;
510 }
511 (*pi->driver->Disable) (pi);
512 pDev->on = FALSE0;
513 }
514
515 if (!pi->driver->Fini)
516 return BadImplementation17;
517
518 (*pi->driver->Fini) (pi);
519
520 KdRemovePointer(pi);
521
522 return Success0;
523 }
524
525 /* NOTREACHED */
526 return BadImplementation17;
527}
528
529Bool
530LegalModifier(unsigned int key, DeviceIntPtr pDev)
531{
532 return TRUE1;
533}
534
535static void
536KdBell(int volume, DeviceIntPtr pDev, void *arg, int something)
537{
538 KeybdCtrl *ctrl = arg;
539 KdKeyboardInfo *ki = NULL((void*)0);
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((void*)0);
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_X16)
617 x_dir = -1;
618 if (randr & RR_Reflect_Y32)
619 y_dir = -1;
620 switch (randr & (RR_Rotate_All(1|2|4|8))) {
621 case RR_Rotate_01:
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_902:
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_1804:
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_2708:
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 BadImplementation17;
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 BadImplementation17;
705 }
706
707 switch (onoff) {
708 case DEVICE_INIT0:
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 BadImplementation17;
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 !Success0;
724 }
725 free(ki->driverPrivate);
726 ki->driverPrivate = NULL((void*)0);
727 }
728
729 if (!ki->driver->Init) {
730 ErrorF("Keyboard %s: no init function\n", ki->name);
731 return BadImplementation17;
732 }
733
734 if ((*ki->driver->Init) (ki) != Success0) {
735 return !Success0;
736 }
737
738 memset(&rmlvo, 0, sizeof(rmlvo))__builtin___memset_chk (&rmlvo, 0, sizeof(rmlvo), __builtin_object_size
(&rmlvo, 0))
;
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 BadImplementation17;
748 }
749
750 xiclass = AtomFromName(XI_KEYBOARD)MakeAtom("KEYBOARD", strlen("KEYBOARD"), 1);
751 AssignTypeAndName(pDevice, xiclass,
752 ki->name ? ki->name : "Generic KDrive Keyboard");
753
754 KdResetInputMachine();
755
756 return Success0;
757
758 case DEVICE_ON1:
759 if (pDev->on == TRUE1)
760 return Success0;
761
762 if (!ki->driver->Enable)
763 return BadImplementation17;
764
765 if ((*ki->driver->Enable) (ki) != Success0) {
766 return BadMatch8;
767 }
768
769 pDev->on = TRUE1;
770 return Success0;
771
772 case DEVICE_OFF2:
773 if (pDev->on == FALSE0)
774 return Success0;
775
776 if (!ki->driver->Disable)
777 return BadImplementation17;
778
779 (*ki->driver->Disable) (ki);
780 pDev->on = FALSE0;
781
782 return Success0;
783
784 break;
785
786 case DEVICE_CLOSE3:
787 if (pDev->on) {
788 if (!ki->driver->Disable)
789 return BadImplementation17;
790
791 (*ki->driver->Disable) (ki);
792 pDev->on = FALSE0;
793 }
794
795 if (!ki->driver->Fini)
796 return BadImplementation17;
797
798 (*ki->driver->Fini) (ki);
799
800 KdRemoveKeyboard(ki);
801
802 return Success0;
803 }
804
805 /* NOTREACHED */
806 return BadImplementation17;
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((void*)0);
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((void*)0);
871}
872
873KdKeyboardInfo *
874KdNewKeyboard(void)
875{
876 KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1);
5
Memory is allocated
877
878 if (!ki)
6
Assuming 'ki' is non-null
7
Taking false branch
879 return NULL((void*)0);
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((void*)0);
887 ki->options = NULL((void*)0);
888 ki->xkbRules = strdup(XKB_DFLT_RULES"base");
889 ki->xkbModel = strdup(XKB_DFLT_MODEL"pc105");
890 ki->xkbLayout = strdup(XKB_DFLT_LAYOUT"us");
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 Success0;
904
905 new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
906 if (!new)
907 return BadAlloc11;
908
909 new->line = strdup(keyboard);
910 new->next = NULL((void*)0);
911
912 for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next);
913 *prev = new;
914
915 return Success0;
916}
917
918int
919KdAddKeyboard(KdKeyboardInfo * ki)
920{
921 KdKeyboardInfo **prev;
922
923 if (!ki)
924 return !Success0;
925
926 ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE1);
927 if (!ki->dixdev) {
928 ErrorF("Couldn't register keyboard device %s\n",
929 ki->name ? ki->name : "(unnamed)");
930 return !Success0;
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 Success0;
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 Success0;
968
969 new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1);
970 if (!new)
971 return BadAlloc11;
972
973 new->line = strdup(pointer);
974 new->next = NULL((void*)0);
975
976 for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next);
977 *prev = new;
978
979 return Success0;
980}
981
982int
983KdAddPointer(KdPointerInfo * pi)
984{
985 KdPointerInfo **prev;
986
987 if (!pi)
988 return Success0;
989
990 pi->mouseState = start;
991 pi->eventHeld = FALSE0;
992
993 pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE1);
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 Success0;
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((void*)0);
1033 char *key = NULL((void*)0), *value = NULL((void*)0);
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((void*)0);
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((void*)0));
1060}
1061
1062static void
1063KdParseKbdOptions(KdKeyboardInfo * ki)
1064{
1065 InputOption *option = NULL((void*)0);
1066
1067 nt_list_for_each_entry(option, ki->options, list.next)for (option = ki->options; option; option = (option)->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((void*)0);
1095 KdKeyboardInfo *ki = NULL((void*)0);
1096
1097 ki = KdNewKeyboard();
4
Calling 'KdNewKeyboard'
8
Returned allocated memory
1098 if (!ki)
9
Taking false branch
1099 return NULL((void*)0);
1100
1101 ki->name = strdup("Unknown KDrive Keyboard");
1102 ki->path = NULL((void*)0);
1103 ki->driver = NULL((void*)0);
1104 ki->driverPrivate = NULL((void*)0);
1105 ki->next = NULL((void*)0);
1106
1107 if (!arg) {
10
Assuming 'arg' is non-null
11
Taking false branch
1108 ErrorF("keybd: no arg\n");
1109 KdFreeKeyboard(ki);
1110 return NULL((void*)0);
1111 }
1112
1113 if (strlen(arg) >= sizeof(save)) {
12
Taking false branch
1114 ErrorF("keybd: arg too long\n");
1115 KdFreeKeyboard(ki);
1116 return NULL((void*)0);
1117 }
1118
1119 arg = KdParseFindNext(arg, ",", save, &delim);
1120 if (!save[0]) {
13
Taking false branch
1121 ErrorF("keybd: failed on save[0]\n");
1122 KdFreeKeyboard(ki);
1123 return NULL((void*)0);
1124 }
1125
1126 if (strcmp(save, "auto") == 0)
14
Taking false branch
1127 ki->driverPrivate = NULL((void*)0);
1128 else
1129 ki->driverPrivate = strdup(save);
1130
1131 if (delim != ',') {
15
Taking false branch
1132 return ki;
1133 }
1134
1135 arg = KdParseFindNext(arg, ",", save, &delim);
1136
1137 while (delim == ',') {
16
Loop condition is false. Execution continues on line 1146
1138 arg = KdParseFindNext(arg, ",", save, &delim);
1139
1140 if (!KdGetOptions(&options, save)) {
1141 KdFreeKeyboard(ki);
1142 return NULL((void*)0);
1143 }
1144 }
1145
1146 if (options) {
17
Taking false branch
1147 ki->options = options;
1148 KdParseKbdOptions(ki);
1149 }
1150
1151 return ki;
1152}
1153
1154static void
1155KdParsePointerOptions(KdPointerInfo * pi)
1156{
1157 InputOption *option = NULL((void*)0);
1158
1159 nt_list_for_each_entry(option, pi->options, list.next)for (option = pi->options; option; option = (option)->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 = TRUE1;
1165 else if (!strcmp(key, "noemulatemiddle"))
1166 pi->emulateMiddleButton = FALSE0;
1167 else if (!strcmp(key, "transformcoord"))
1168 pi->transformCoordinates = TRUE1;
1169 else if (!strcmp(key, "rawcoord"))
1170 pi->transformCoordinates = FALSE0;
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((void*)0);
1187 InputOption *options = NULL((void*)0);
1188 int i = 0;
1189
1190 pi = KdNewPointer();
1191 if (!pi)
1192 return NULL((void*)0);
1193 pi->emulateMiddleButton = kdEmulateMiddleButton;
1194 pi->transformCoordinates = !kdRawPointerCoordinates;
1195 pi->protocol = NULL((void*)0);
1196 pi->nButtons = 5; /* XXX should not be hardcoded */
1197 pi->inputClass = KD_MOUSE2;
1198
1199 if (!arg) {
1200 ErrorF("mouse: no arg\n");
1201 KdFreePointer(pi);
1202 return NULL((void*)0);
1203 }
1204
1205 if (strlen(arg) >= sizeof(save)) {
1206 ErrorF("mouse: arg too long\n");
1207 KdFreePointer(pi);
1208 return NULL((void*)0);
1209 }
1210 arg = KdParseFindNext(arg, ",", save, &delim);
1211 if (!save[0]) {
1212 ErrorF("failed on save[0]\n");
1213 KdFreePointer(pi);
1214 return NULL((void*)0);
1215 }
1216
1217 if (strcmp(save, "auto") == 0)
1218 pi->driverPrivate = NULL((void*)0);
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((void*)0);
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 = TRUE1;
1266
1267 for (dev = kdConfigPointers; dev; dev = dev->next) {
1
Loop condition is false. Execution continues on line 1274
1268 pi = KdParsePointer(dev->line);
1269 if (!pi)
1270 ErrorF("Failed to parse pointer\n");
1271 if (KdAddPointer(pi) != Success0)
1272 ErrorF("Failed to add pointer!\n");
1273 }
1274 for (dev = kdConfigKeyboards; dev; dev = dev->next) {
2
Loop condition is true. Entering loop body
21
Loop condition is false. Execution continues on line 1282
1275 ki = KdParseKeyboard(dev->line);
3
Calling 'KdParseKeyboard'
18
Returned allocated memory
1276 if (!ki)
19
Taking false branch
1277 ErrorF("Failed to parse keyboard\n");
1278 if (KdAddKeyboard(ki) != Success0)
20
Taking true branch
1279 ErrorF("Failed to add keyboard!\n");
1280 }
1281
1282 mieqInit();
22
Potential leak of memory pointed to by 'ki'
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_ACTIONS2 2
1447
1448typedef struct _inputTransition {
1449 KdInputAction actions[MAX_ACTIONS2];
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_WINDOW10 10
1593#define EMULATION_TIMEOUT100 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_WINDOW10 &&
1602 abs(pi->emulationDy) < EMULATION_WINDOW10);
1603}
1604
1605static KdInputClass
1606KdClassifyInput(KdPointerInfo * pi, int type, int x, int y, int z, int b)
1607{
1608 switch (type) {
1609 case ButtonPress4:
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 ButtonRelease5:
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 MotionNotify6:
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/* We return true if we're stealing the event. */
1645static Bool
1646KdRunMouseMachine(KdPointerInfo * pi, KdInputClass c, int type, int x, int y,
1647 int z, int b, int absrel)
1648{
1649 const KdInputTransition *t;
1650 int a;
1651
1652 c = KdClassifyInput(pi, type, x, y, z, b);
1653 t = &kdInputMachine[pi->mouseState][c];
1654 for (a = 0; a < MAX_ACTIONS2; a++) {
1655 switch (t->actions[a]) {
1656 case noop:
1657 break;
1658 case hold:
1659 pi->eventHeld = TRUE1;
1660 pi->emulationDx = 0;
1661 pi->emulationDy = 0;
1662 pi->heldEvent.type = type;
1663 pi->heldEvent.x = x;
1664 pi->heldEvent.y = y;
1665 pi->heldEvent.z = z;
1666 pi->heldEvent.flags = b;
1667 pi->heldEvent.absrel = absrel;
1668 return TRUE1;
1669 break;
1670 case setto:
1671 pi->emulationTimeout = GetTimeInMillis() + EMULATION_TIMEOUT100;
1672 pi->timeoutPending = TRUE1;
1673 break;
1674 case deliver:
1675 _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x,
1676 pi->heldEvent.y, pi->heldEvent.z,
1677 pi->heldEvent.flags, pi->heldEvent.absrel,
1678 TRUE1);
1679 break;
1680 case release:
1681 pi->eventHeld = FALSE0;
1682 pi->timeoutPending = FALSE0;
1683 _KdEnqueuePointerEvent(pi, pi->heldEvent.type, pi->heldEvent.x,
1684 pi->heldEvent.y, pi->heldEvent.z,
1685 pi->heldEvent.flags, pi->heldEvent.absrel,
1686 TRUE1);
1687 return TRUE1;
1688 break;
1689 case clearto:
1690 pi->timeoutPending = FALSE0;
1691 break;
1692 case gen_down_2:
1693 _KdEnqueuePointerEvent(pi, ButtonPress4, x, y, z, 2, absrel, TRUE1);
1694 pi->eventHeld = FALSE0;
1695 return TRUE1;
1696 break;
1697 case gen_up_2:
1698 _KdEnqueuePointerEvent(pi, ButtonRelease5, x, y, z, 2, absrel, TRUE1);
1699 return TRUE1;
1700 break;
1701 }
1702 }
1703 pi->mouseState = t->nextState;
1704 return FALSE0;
1705}
1706
1707static int
1708KdHandlePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z, int b,
1709 int absrel)
1710{
1711 if (pi->emulateMiddleButton)
1712 return KdRunMouseMachine(pi, KdClassifyInput(pi, type, x, y, z, b),
1713 type, x, y, z, b, absrel);
1714 return FALSE0;
1715}
1716
1717static void
1718KdReceiveTimeout(KdPointerInfo * pi)
1719{
1720 KdRunMouseMachine(pi, timeout, 0, 0, 0, 0, 0, 0);
1721}
1722
1723/*
1724 * kdCheckTermination
1725 *
1726 * This function checks for the key sequence that terminates the server. When
1727 * detected, it sets the dispatchException flag and returns. The key sequence
1728 * is:
1729 * Control-Alt
1730 * It's assumed that the server will be waken up by the caller when this
1731 * function returns.
1732 */
1733
1734extern int nClients;
1735
1736void
1737KdReleaseAllKeys(void)
1738{
1739#if 0
1740 int key;
1741 KdKeyboardInfo *ki;
1742
1743 OsBlockSIGIO();
1744
1745 for (ki = kdKeyboards; ki; ki = ki->next) {
1746 for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; key++) {
1747 if (key_is_down(ki->dixdev, key, KEY_POSTED2 | KEY_PROCESSED1)) {
1748 KdHandleKeyboardEvent(ki, KeyRelease3, key);
1749 QueueGetKeyboardEvents(ki->dixdev, KeyRelease3, key, NULL((void*)0));
1750 }
1751 }
1752 }
1753
1754 OsReleaseSIGIO();
1755#endif
1756}
1757
1758static void
1759KdCheckLock(void)
1760{
1761 KeyClassPtr keyc = NULL((void*)0);
1762 Bool isSet = FALSE0, shouldBeSet = FALSE0;
1763 KdKeyboardInfo *tmp = NULL((void*)0);
1764
1765 for (tmp = kdKeyboards; tmp; tmp = tmp->next) {
1766 if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) {
1767 keyc = tmp->dixdev->key;
1768 isSet = (tmp->leds & (1 << (tmp->LockLed - 1))) != 0;
1769 /* FIXME: Just use XKB indicators! */
1770 shouldBeSet =
1771 ! !(XkbStateFieldFromRec(&keyc->xkbInfo->state)(((((&keyc->xkbInfo->state)->group)&0x3)<<
13)|(((&keyc->xkbInfo->state)->lookup_mods)&
0xff))
& LockMask(1<<1));
1772 if (isSet != shouldBeSet)
1773 KdSetLed(tmp, tmp->LockLed, shouldBeSet);
1774 }
1775 }
1776}
1777
1778void
1779KdEnqueueKeyboardEvent(KdKeyboardInfo * ki,
1780 unsigned char scan_code, unsigned char is_up)
1781{
1782 unsigned char key_code;
1783 int type;
1784
1785 if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key)
1786 return;
1787
1788 if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) {
1789 key_code = scan_code + KD_MIN_KEYCODE8 - ki->minScanCode;
1790
1791 /*
1792 * Set up this event -- the type may be modified below
1793 */
1794 if (is_up)
1795 type = KeyRelease3;
1796 else
1797 type = KeyPress2;
1798
1799 QueueKeyboardEvents(ki->dixdev, type, key_code);
1800 }
1801 else {
1802 ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
1803 ki->name, scan_code, ki->minScanCode, ki->maxScanCode);
1804 }
1805}
1806
1807/*
1808 * kdEnqueuePointerEvent
1809 *
1810 * This function converts hardware mouse event information into X event
1811 * information. A mouse movement event is passed off to MI to generate
1812 * a MotionNotify event, if appropriate. Button events are created and
1813 * passed off to MI for enqueueing.
1814 */
1815
1816/* FIXME do something a little more clever to deal with multiple axes here */
1817void
1818KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry,
1819 int rz)
1820{
1821 unsigned char buttons;
1822 int x, y, z;
1823 int (*matrix)[3] = kdPointerMatrix.matrix;
1824 unsigned long button;
1825 int n;
1826 int dixflags = 0;
1827
1828 if (!pi)
1829 return;
1830
1831 /* we don't need to transform z, so we don't. */
1832 if (flags & KD_MOUSE_DELTA0x80000000) {
1833 if (pi->transformCoordinates) {
1834 x = matrix[0][0] * rx + matrix[0][1] * ry;
1835 y = matrix[1][0] * rx + matrix[1][1] * ry;
1836 }
1837 else {
1838 x = rx;
1839 y = ry;
1840 }
1841 }
1842 else {
1843 if (pi->transformCoordinates) {
1844 x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2];
1845 y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2];
1846 }
1847 else {
1848 x = rx;
1849 y = ry;
1850 }
1851 }
1852 z = rz;
1853
1854 if (flags & KD_MOUSE_DELTA0x80000000) {
1855 if (x || y || z) {
1856 dixflags = POINTER_RELATIVE(1 << 1) | POINTER_ACCELERATE(1 << 3);
1857 _KdEnqueuePointerEvent(pi, MotionNotify6, x, y, z, 0, dixflags,
1858 FALSE0);
1859 }
1860 }
1861 else {
1862 dixflags = POINTER_ABSOLUTE(1 << 2);
1863 if (flags & KD_POINTER_DESKTOP0x40000000)
1864 dixflags |= POINTER_DESKTOP(1 << 7);
1865 if (x != pi->dixdev->last.valuators[0] ||
1866 y != pi->dixdev->last.valuators[1])
1867 _KdEnqueuePointerEvent(pi, MotionNotify6, x, y, z, 0, dixflags,
1868 FALSE0);
1869 }
1870
1871 buttons = flags;
1872
1873 for (button = KD_BUTTON_10x01, n = 1; n <= pi->nButtons; button <<= 1, n++) {
1874 if (((pi->buttonState & button) ^ (buttons & button)) &&
1875 !(buttons & button)) {
1876 _KdEnqueuePointerEvent(pi, ButtonRelease5, x, y, z, n,
1877 dixflags, FALSE0);
1878 }
1879 }
1880 for (button = KD_BUTTON_10x01, n = 1; n <= pi->nButtons; button <<= 1, n++) {
1881 if (((pi->buttonState & button) ^ (buttons & button)) &&
1882 (buttons & button)) {
1883 _KdEnqueuePointerEvent(pi, ButtonPress4, x, y, z, n,
1884 dixflags, FALSE0);
1885 }
1886 }
1887
1888 pi->buttonState = buttons;
1889}
1890
1891void
1892_KdEnqueuePointerEvent(KdPointerInfo * pi, int type, int x, int y, int z,
1893 int b, int absrel, Bool force)
1894{
1895 int valuators[3] = { x, y, z };
1896 ValuatorMask mask;
1897
1898 /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
1899 if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
1900 return;
1901
1902 valuator_mask_set_range(&mask, 0, 3, valuators);
1903
1904 QueuePointerEvents(pi->dixdev, type, b, absrel, &mask);
1905}
1906
1907void
1908KdBlockHandler(ScreenPtr pScreen, void *timeo, void *readmask)
1909{
1910 KdPointerInfo *pi;
1911 int myTimeout = 0;
1912
1913 for (pi = kdPointers; pi; pi = pi->next) {
1914 if (pi->timeoutPending) {
1915 int ms;
1916
1917 ms = pi->emulationTimeout - GetTimeInMillis();
1918 if (ms < 1)
1919 ms = 1;
1920 if (ms < myTimeout || myTimeout == 0)
1921 myTimeout = ms;
1922 }
1923 }
1924 /* if we need to poll for events, do that */
1925 if (kdOsFuncs->pollEvents) {
1926 (*kdOsFuncs->pollEvents) ();
1927 myTimeout = 20;
1928 }
1929 if (myTimeout > 0)
1930 AdjustWaitForDelay(timeo, myTimeout);
1931}
1932
1933void
1934KdWakeupHandler(ScreenPtr pScreen, unsigned long lresult, void *readmask)
1935{
1936 int result = (int) lresult;
1937 fd_set *pReadmask = (fd_set *) readmask;
1938 int i;
1939 KdPointerInfo *pi;
1940
1941 if (kdInputEnabled && result > 0) {
1942 for (i = 0; i < kdNumInputFds; i++)
1943 if (FD_ISSET(kdInputFds[i].fd, pReadmask)__darwin_fd_isset((kdInputFds[i].fd), (pReadmask))) {
1944 OsBlockSIGIO();
1945 (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
1946 OsReleaseSIGIO();
1947 }
1948 }
1949 for (pi = kdPointers; pi; pi = pi->next) {
1950 if (pi->timeoutPending) {
1951 if ((long) (GetTimeInMillis() - pi->emulationTimeout) >= 0) {
1952 pi->timeoutPending = FALSE0;
1953 OsBlockSIGIO();
1954 KdReceiveTimeout(pi);
1955 OsReleaseSIGIO();
1956 }
1957 }
1958 }
1959 if (kdSwitchPending)
1960 KdProcessSwitch();
1961}
1962
1963#define KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)->
devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin
))
(&(KdGetScreenPriv(pScreen)((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates
, (&kdScreenPrivateKeyRec)))
->screen->origin))
1964
1965static Bool
1966KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
1967{
1968 ScreenPtr pScreen = *ppScreen;
1969 ScreenPtr pNewScreen;
1970 int n;
1971 int dx, dy;
1972 int best_x, best_y;
1973 int n_best_x, n_best_y;
1974 CARD32 ms;
1975
1976 if (kdDisableZaphod || screenInfo.numScreens <= 1)
1977 return FALSE0;
1978
1979 if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
1980 return FALSE0;
1981
1982 ms = GetTimeInMillis();
1983 if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
1984 return FALSE0;
1985 kdOffScreen = TRUE1;
1986 kdOffScreenTime = ms;
1987 n_best_x = -1;
1988 best_x = 32767;
1989 n_best_y = -1;
1990 best_y = 32767;
1991 for (n = 0; n < screenInfo.numScreens; n++) {
1992 pNewScreen = screenInfo.screens[n];
1993 if (pNewScreen == pScreen)
1994 continue;
1995 dx = KdScreenOrigin(pNewScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pNewScreen)->
devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin
))
->x - KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)->
devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin
))
->x;
1996 dy = KdScreenOrigin(pNewScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pNewScreen)->
devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin
))
->y - KdScreenOrigin(pScreen)(&(((KdPrivScreenPtr) dixLookupPrivate(&(pScreen)->
devPrivates, (&kdScreenPrivateKeyRec)))->screen->origin
))
->y;
1997 if (*x < 0) {
1998 if (dx < 0 && -dx < best_x) {
1999 best_x = -dx;
2000 n_best_x = n;
2001 }
2002 }
2003 else if (*x >= pScreen->width) {
2004 if (dx > 0 && dx < best_x) {
2005 best_x = dx;
2006 n_best_x = n;
2007 }
2008 }
2009 if (*y < 0) {
2010 if (dy < 0 && -dy < best_y) {
2011 best_y = -dy;
2012 n_best_y = n;
2013 }
2014 }
2015 else if (*y >= pScreen->height) {
2016 if (dy > 0 && dy < best_y) {
2017 best_y = dy;
2018 n_best_y = n;
2019 }
2020 }
2021 }
2022 if (best_y < best_x)
2023 n_best_x = n_best_y;
2024 if (n_best_x == -1)
2025 return FALSE0;
2026 pNewScreen = screenInfo.screens[n_best_x];
2027
2028 if (*x < 0)
2029 *x += pNewScreen->width;
2030 if (*y < 0)
2031 *y += pNewScreen->height;
2032
2033 if (*x >= pScreen->width)
2034 *x -= pScreen->width;
2035 if (*y >= pScreen->height)
2036 *y -= pScreen->height;
2037
2038 *ppScreen = pNewScreen;
2039 return TRUE1;
2040}
2041
2042static void
2043KdCrossScreen(ScreenPtr pScreen, Bool entering)
2044{
2045}
2046
2047int KdCurScreen; /* current event screen */
2048
2049static void
2050KdWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
2051{
2052 OsBlockSIGIO();
2053 KdCurScreen = pScreen->myNum;
2054 miPointerWarpCursor(pDev, pScreen, x, y);
2055 OsReleaseSIGIO();
2056}
2057
2058miPointerScreenFuncRec kdPointerScreenFuncs = {
2059 KdCursorOffScreen,
2060 KdCrossScreen,
2061 KdWarpCursor
2062};
2063
2064void
2065ProcessInputEvents(void)
2066{
2067 mieqProcessInputEvents();
2068 if (kdSwitchPending)
2069 KdProcessSwitch();
2070 KdCheckLock();
2071}
2072
2073/* At the moment, absolute/relative is up to the client. */
2074int
2075SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode)
2076{
2077 return BadMatch8;
2078}
2079
2080int
2081SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev,
2082 int *valuators, int first_valuator, int num_valuators)
2083{
2084 return BadMatch8;
2085}
2086
2087int
2088ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
2089 xDeviceCtl * control)
2090{
2091 switch (control->control) {
2092 case DEVICE_RESOLUTION1:
2093 /* FIXME do something more intelligent here */
2094 return BadMatch8;
2095
2096 case DEVICE_ABS_CALIB2:
2097 case DEVICE_ABS_AREA5:
2098 case DEVICE_CORE3:
2099 return BadMatch8;
2100 case DEVICE_ENABLE4:
2101 return Success0;
2102
2103 default:
2104 return BadMatch8;
2105 }
2106
2107 /* NOTREACHED */
2108 return BadImplementation17;
2109}
2110
2111int
2112NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
2113 DeviceIntPtr *pdev)
2114{
2115 InputOption *option = NULL((void*)0);
2116 KdPointerInfo *pi = NULL((void*)0);
2117 KdKeyboardInfo *ki = NULL((void*)0);
2118
2119 nt_list_for_each_entry(option, options, list.next)for (option = options; option; option = (option)->list.next
)
{
2120 const char *key = input_option_get_key(option);
2121 const char *value = input_option_get_value(option);
2122
2123 if (strcmp(key, "type") == 0) {
2124 if (strcmp(value, "pointer") == 0) {
2125 pi = KdNewPointer();
2126 if (!pi)
2127 return BadAlloc11;
2128 }
2129 else if (strcmp(value, "keyboard") == 0) {
2130 ki = KdNewKeyboard();
2131 if (!ki)
2132 return BadAlloc11;
2133 }
2134 else {
2135 ErrorF("unrecognised device type!\n");
2136 return BadValue2;
2137 }
2138 }
2139#ifdef CONFIG_HAL
2140 else if (strcmp(key, "_source") == 0 &&
2141 strcmp(value, "server/hal") == 0) {
2142 ErrorF("Ignoring device from HAL.\n");
2143 return BadValue2;
2144 }
2145#endif
2146#ifdef CONFIG_UDEV
2147 else if (strcmp(key, "_source") == 0 &&
2148 strcmp(value, "server/udev") == 0) {
2149 ErrorF("Ignoring device from udev.\n");
2150 return BadValue2;
2151 }
2152#endif
2153 }
2154
2155 if (!ki && !pi) {
2156 ErrorF("unrecognised device identifier!\n");
2157 return BadValue2;
2158 }
2159
2160 /* FIXME: change this code below to use KdParseKbdOptions and
2161 * KdParsePointerOptions */
2162 nt_list_for_each_entry(option, options, list.next)for (option = options; option; option = (option)->list.next
)
{
2163 const char *key = input_option_get_key(option);
2164 const char *value = input_option_get_value(option);
2165
2166 if (strcmp(key, "device") == 0) {
2167 if (pi && value)
2168 pi->path = strdup(value);
2169 else if (ki && value)
2170 ki->path = strdup(value);
2171 }
2172 else if (strcmp(key, "driver") == 0) {
2173 if (pi) {
2174 pi->driver = KdFindPointerDriver(value);
2175 if (!pi->driver) {
2176 ErrorF("couldn't find driver!\n");
2177 KdFreePointer(pi);
2178 return BadValue2;
2179 }
2180 pi->options = options;
2181 }
2182 else if (ki) {
2183 ki->driver = KdFindKeyboardDriver(value);
2184 if (!ki->driver) {
2185 ErrorF("couldn't find driver!\n");
2186 KdFreeKeyboard(ki);
2187 return BadValue2;
2188 }
2189 ki->options = options;
2190 }
2191 }
2192 }
2193
2194 if (pi) {
2195 if (KdAddPointer(pi) != Success0 ||
2196 ActivateDevice(pi->dixdev, TRUE1) != Success0 ||
2197 EnableDevice(pi->dixdev, TRUE1) != TRUE1) {
2198 ErrorF("couldn't add or enable pointer\n");
2199 return BadImplementation17;
2200 }
2201 }
2202 else if (ki) {
2203 if (KdAddKeyboard(ki) != Success0 ||
2204 ActivateDevice(ki->dixdev, TRUE1) != Success0 ||
2205 EnableDevice(ki->dixdev, TRUE1) != TRUE1) {
2206 ErrorF("couldn't add or enable keyboard\n");
2207 return BadImplementation17;
2208 }
2209 }
2210
2211 if (pi) {
2212 *pdev = pi->dixdev;
2213 }
2214 else if (ki) {
2215 *pdev = ki->dixdev;
2216 }
2217
2218 return Success0;
2219}
2220
2221void
2222DeleteInputDeviceRequest(DeviceIntPtr pDev)
2223{
2224 RemoveDevice(pDev, TRUE1);
2225}