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