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