sunKbd.c revision 0ea8fa60
1/* $Xorg: sunKbd.c,v 1.3 2000/08/17 19:48:30 cpqbld Exp $ */ 2/*- 3 * Copyright 1987 by the Regents of the University of California 4 * 5 * Permission to use, copy, modify, and distribute this 6 * software and its documentation for any purpose and without 7 * fee is hereby granted, provided that the above copyright 8 * notice appear in all copies. The University of California 9 * makes no representations about the suitability of this 10 * software for any purpose. It is provided "as is" without 11 * express or implied warranty. 12 */ 13 14/************************************************************ 15Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. 16 17 All Rights Reserved 18 19Permission to use, copy, modify, and distribute this 20software and its documentation for any purpose and without 21fee is hereby granted, provided that the above copyright no- 22tice appear in all copies and that both that copyright no- 23tice and this permission notice appear in supporting docu- 24mentation, and that the names of Sun or The Open Group 25not be used in advertising or publicity pertaining to 26distribution of the software without specific prior 27written permission. Sun and The Open Group make no 28representations about the suitability of this software for 29any purpose. It is provided "as is" without any express or 30implied warranty. 31 32SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 33INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 34NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 35ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 36ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 37PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 38OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 39THE USE OR PERFORMANCE OF THIS SOFTWARE. 40 41********************************************************/ 42/* $XFree86: xc/programs/Xserver/hw/sun/sunKbd.c,v 1.9 2003/11/17 22:20:36 dawes Exp $ */ 43 44#define NEED_EVENTS 45#include "sun.h" 46#include <X11/keysym.h> 47#include <X11/Sunkeysym.h> 48#include "mi.h" 49 50#include <X11/extensions/XKB.h> 51#include "xkbsrv.h" 52#include "xkbstr.h" 53 54#ifdef __sun 55#define SUN_LED_MASK 0x0f 56#else 57#define SUN_LED_MASK 0x07 58#endif 59#define MIN_KEYCODE 7 /* necessary to avoid the mouse buttons */ 60#define MAX_KEYCODE 255 /* limited by the protocol */ 61#define NUM_KEYCODES (MAX_KEYCODE - MIN_KEYCODE + 1) 62#ifndef KB_SUN4 63#define KB_SUN4 4 64#endif 65 66#define Meta_Mask Mod1Mask 67#define Mode_switch_Mask Mod2Mask 68#define Alt_Mask Mod3Mask 69#define Num_Lock_Mask Mod4Mask 70#define ScrollLockMask Mod5Mask 71 72#define tvminus(tv, tv1, tv2) /* tv = tv1 - tv2 */ \ 73 if ((tv1).tv_usec < (tv2).tv_usec) { \ 74 (tv1).tv_usec += 1000000; \ 75 (tv1).tv_sec -= 1; \ 76 } \ 77 (tv).tv_usec = (tv1).tv_usec - (tv2).tv_usec; \ 78 (tv).tv_sec = (tv1).tv_sec - (tv2).tv_sec; 79 80#define tvplus(tv, tv1, tv2) /* tv = tv1 + tv2 */ \ 81 (tv).tv_sec = (tv1).tv_sec + (tv2).tv_sec; \ 82 (tv).tv_usec = (tv1).tv_usec + (tv2).tv_usec; \ 83 if ((tv).tv_usec > 1000000) { \ 84 (tv).tv_usec -= 1000000; \ 85 (tv).tv_sec += 1; \ 86 } 87 88static void sunKbdHandlerNotify(int, int, void *); 89static void sunInitModMap(const KeySymsRec *, CARD8 *); 90static void SwapLKeys(KeySymsRec *); 91static void SetLights(KeybdCtrl *, int); 92static KeyCode LookupKeyCode(KeySym, XkbDescPtr, KeySymsPtr); 93static void pseudoKey(DeviceIntPtr, Bool, KeyCode); 94static void DoLEDs(DeviceIntPtr, KeybdCtrl *, sunKbdPrivPtr); 95 96DeviceIntPtr sunKeyboardDevice = NULL; 97 98static void 99sunKbdHandlerNotify(int fd __unused, int ready __unused, void *data __unused) 100{ 101} 102 103void 104sunKbdWait(void) 105{ 106 static struct timeval lastChngKbdTransTv; 107 struct timeval tv; 108 struct timeval lastChngKbdDeltaTv; 109 unsigned int lastChngKbdDelta; 110 111 X_GETTIMEOFDAY(&tv); 112 if (!lastChngKbdTransTv.tv_sec) 113 lastChngKbdTransTv = tv; 114 tvminus(lastChngKbdDeltaTv, tv, lastChngKbdTransTv); 115 lastChngKbdDelta = TVTOMILLI(lastChngKbdDeltaTv); 116 if (lastChngKbdDelta < 750) { 117 unsigned wait; 118 /* 119 * We need to guarantee at least 750 milliseconds between 120 * calls to KIOCTRANS. YUCK! 121 */ 122 wait = (750L - lastChngKbdDelta) * 1000L; 123 usleep (wait); 124 X_GETTIMEOFDAY(&tv); 125 } 126 lastChngKbdTransTv = tv; 127} 128 129static 130void SwapLKeys(KeySymsRec* keysyms) 131{ 132 unsigned int i; 133 KeySym k; 134 135 for (i = 2; i < keysyms->maxKeyCode * keysyms->mapWidth; i++) 136 if (keysyms->map[i] == XK_L1 || 137 keysyms->map[i] == XK_L2 || 138 keysyms->map[i] == XK_L3 || 139 keysyms->map[i] == XK_L4 || 140 keysyms->map[i] == XK_L5 || 141 keysyms->map[i] == XK_L6 || 142 keysyms->map[i] == XK_L7 || 143 keysyms->map[i] == XK_L8 || 144 keysyms->map[i] == XK_L9 || 145 keysyms->map[i] == XK_L10) { 146 /* yes, I could have done a clever two line swap! */ 147 k = keysyms->map[i - 2]; 148 keysyms->map[i - 2] = keysyms->map[i]; 149 keysyms->map[i] = k; 150 } 151} 152 153static void 154SetLights(KeybdCtrl* ctrl, int fd) 155{ 156#ifdef KIOCSLED 157 static unsigned char led_tab[16] = { 158 0, 159#ifdef __sun 160 LED_NUM_LOCK, 161 LED_SCROLL_LOCK, 162 LED_SCROLL_LOCK | LED_NUM_LOCK, 163 LED_COMPOSE, 164 LED_COMPOSE | LED_NUM_LOCK, 165 LED_COMPOSE | LED_SCROLL_LOCK, 166 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK, 167 LED_CAPS_LOCK, 168 LED_CAPS_LOCK | LED_NUM_LOCK, 169 LED_CAPS_LOCK | LED_SCROLL_LOCK, 170 LED_CAPS_LOCK | LED_SCROLL_LOCK | LED_NUM_LOCK, 171 LED_CAPS_LOCK | LED_COMPOSE, 172 LED_CAPS_LOCK | LED_COMPOSE | LED_NUM_LOCK, 173 LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK, 174 LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK 175#else 176 LED_CAPS_LOCK, 177 LED_NUM_LOCK, 178 LED_NUM_LOCK | LED_CAPS_LOCK, 179 LED_SCROLL_LOCK, 180 LED_SCROLL_LOCK | LED_CAPS_LOCK, 181 LED_SCROLL_LOCK | LED_NUM_LOCK, 182 LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK, 183 LED_COMPOSE, 184 LED_COMPOSE | LED_CAPS_LOCK, 185 LED_COMPOSE | LED_NUM_LOCK, 186 LED_COMPOSE | LED_NUM_LOCK | LED_CAPS_LOCK, 187 LED_COMPOSE | LED_SCROLL_LOCK, 188 LED_COMPOSE | LED_SCROLL_LOCK | LED_CAPS_LOCK, 189 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK, 190 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK, 191#endif 192 }; 193 if (ioctl (fd, KIOCSLED, (caddr_t)&led_tab[ctrl->leds & SUN_LED_MASK]) == -1) 194 ErrorF("Failed to set keyboard lights"); 195#endif 196} 197 198 199/*- 200 *----------------------------------------------------------------------- 201 * sunBell -- 202 * Ring the terminal/keyboard bell 203 * 204 * Results: 205 * Ring the keyboard bell for an amount of time proportional to 206 * "loudness." 207 * 208 * Side Effects: 209 * None, really... 210 * 211 *----------------------------------------------------------------------- 212 */ 213 214static void 215bell(int fd, int duration) 216{ 217 int kbdCmd; /* Command to give keyboard */ 218 219 kbdCmd = KBD_CMD_BELL; 220 if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) { 221 ErrorF("Failed to activate bell"); 222 return; 223 } 224 if (duration) usleep (duration); 225 kbdCmd = KBD_CMD_NOBELL; 226 if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) 227 ErrorF("Failed to deactivate bell"); 228} 229 230static void 231sunBell(int percent, DeviceIntPtr device, void *ctrl, int unused) 232{ 233 KeybdCtrl* kctrl = (KeybdCtrl*) ctrl; 234 sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate; 235 236 if (percent == 0 || kctrl->bell == 0) 237 return; 238 239 bell (pPriv->fd, kctrl->bell_duration * 1000); 240} 241 242void 243DDXRingBell(int volume, int pitch, int duration) 244{ 245 DeviceIntPtr pKeyboard; 246 sunKbdPrivPtr pPriv; 247 248 pKeyboard = sunKeyboardDevice; 249 if (pKeyboard != NULL) { 250 pPriv = (sunKbdPrivPtr)pKeyboard->public.devicePrivate; 251 bell(pPriv->fd, duration * 1000); 252 } 253} 254 255 256#ifdef __sun 257#define XLED_NUM_LOCK 0x1 258#define XLED_COMPOSE 0x4 259#define XLED_SCROLL_LOCK 0x2 260#define XLED_CAPS_LOCK 0x8 261#else 262#define XLED_NUM_LOCK 0x2 263#define XLED_COMPOSE 0x8 264#define XLED_SCROLL_LOCK 0x4 265#define XLED_CAPS_LOCK 0x1 266#endif 267 268static KeyCode 269LookupKeyCode(KeySym keysym, XkbDescPtr xkb, KeySymsPtr syms) 270{ 271 KeyCode i; 272 int ii, index = 0; 273 274 for (i = xkb->min_key_code; i < xkb->max_key_code; i++) 275 for (ii = 0; ii < syms->mapWidth; ii++) 276 if (syms->map[index++] == keysym) 277 return i; 278 return 0; 279} 280 281static void 282pseudoKey(DeviceIntPtr device, Bool down, KeyCode keycode) 283{ 284 int bit; 285 CARD8 modifiers; 286 CARD16 mask; 287 BYTE* kptr; 288 289 kptr = &device->key->down[keycode >> 3]; 290 bit = 1 << (keycode & 7); 291 modifiers = device->key->xkbInfo->desc->map->modmap[keycode]; 292 if (down) { 293 /* fool dix into thinking this key is now "down" */ 294 int i; 295 *kptr |= bit; 296 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 297 if (mask & modifiers) { 298 device->key->modifierKeyCount[i]++; 299 modifiers &= ~mask; 300 } 301 } else { 302 /* fool dix into thinking this key is now "up" */ 303 if (*kptr & bit) { 304 int i; 305 *kptr &= ~bit; 306 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 307 if (mask & modifiers) { 308 if (--device->key->modifierKeyCount[i] <= 0) { 309 device->key->modifierKeyCount[i] = 0; 310 } 311 modifiers &= ~mask; 312 } 313 } 314 } 315} 316 317static void 318DoLEDs( 319 DeviceIntPtr device, /* Keyboard to alter */ 320 KeybdCtrl* ctrl, 321 sunKbdPrivPtr pPriv 322) 323{ 324 XkbDescPtr xkb; 325 KeySymsPtr syms; 326 327 xkb = device->key->xkbInfo->desc; 328 syms = XkbGetCoreMap(device); 329 if (!syms) 330 return; /* XXX */ 331 332 if ((ctrl->leds & XLED_CAPS_LOCK) && !(pPriv->leds & XLED_CAPS_LOCK)) 333 pseudoKey(device, TRUE, 334 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 335 336 if (!(ctrl->leds & XLED_CAPS_LOCK) && (pPriv->leds & XLED_CAPS_LOCK)) 337 pseudoKey(device, FALSE, 338 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 339 340 if ((ctrl->leds & XLED_NUM_LOCK) && !(pPriv->leds & XLED_NUM_LOCK)) 341 pseudoKey(device, TRUE, 342 LookupKeyCode(XK_Num_Lock, xkb, syms)); 343 344 if (!(ctrl->leds & XLED_NUM_LOCK) && (pPriv->leds & XLED_NUM_LOCK)) 345 pseudoKey(device, FALSE, 346 LookupKeyCode(XK_Num_Lock, xkb, syms)); 347 348 if ((ctrl->leds & XLED_SCROLL_LOCK) && !(pPriv->leds & XLED_SCROLL_LOCK)) 349 pseudoKey(device, TRUE, 350 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 351 352 if (!(ctrl->leds & XLED_SCROLL_LOCK) && (pPriv->leds & XLED_SCROLL_LOCK)) 353 pseudoKey(device, FALSE, 354 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 355 356 if ((ctrl->leds & XLED_COMPOSE) && !(pPriv->leds & XLED_COMPOSE)) 357 pseudoKey(device, TRUE, 358 LookupKeyCode(SunXK_Compose, xkb, syms)); 359 360 if (!(ctrl->leds & XLED_COMPOSE) && (pPriv->leds & XLED_COMPOSE)) 361 pseudoKey(device, FALSE, 362 LookupKeyCode(SunXK_Compose, xkb, syms)); 363 364 pPriv->leds = ctrl->leds & SUN_LED_MASK; 365 SetLights (ctrl, pPriv->fd); 366 free(syms->map); 367 free(syms); 368} 369 370/*- 371 *----------------------------------------------------------------------- 372 * sunKbdCtrl -- 373 * Alter some of the keyboard control parameters 374 * 375 * Results: 376 * None. 377 * 378 * Side Effects: 379 * Some... 380 * 381 *----------------------------------------------------------------------- 382 */ 383 384static void 385sunKbdCtrl(DeviceIntPtr device, KeybdCtrl* ctrl) 386{ 387 sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate; 388 389 if (pPriv->fd < 0) return; 390 391 if (ctrl->click != pPriv->click) { 392 int kbdClickCmd; 393 394 pPriv->click = ctrl->click; 395 kbdClickCmd = pPriv->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK; 396 if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) == -1) 397 ErrorF("Failed to set keyclick"); 398 } 399 if ((pPriv->type == KB_SUN4) && (pPriv->leds != (ctrl->leds & SUN_LED_MASK))) 400 DoLEDs(device, ctrl, pPriv); 401} 402 403/*- 404 *----------------------------------------------------------------------- 405 * sunInitKbdNames -- 406 * Handle the XKB initialization 407 * 408 * Results: 409 * None. 410 * 411 * Comments: 412 * This function needs considerable work, in conjunctions with 413 * the need to add geometry descriptions of Sun Keyboards. 414 * It would also be nice to have #defines for all the keyboard 415 * layouts so that we don't have to have these hard-coded 416 * numbers. 417 * 418 *----------------------------------------------------------------------- 419 */ 420static void 421sunInitKbdNames(XkbRMLVOSet *rmlvo, sunKbdPrivPtr pKbd) 422{ 423#if 0 /* XXX to be revisited later */ 424#ifndef XKBBUFSIZE 425#define XKBBUFSIZE 64 426#endif 427 static char keycodesbuf[XKBBUFSIZE]; 428 static char geometrybuf[XKBBUFSIZE]; 429 static char symbolsbuf[XKBBUFSIZE]; 430 431 names->keymap = NULL; 432 names->compat = "compat/complete"; 433 names->types = "types/complete"; 434 names->keycodes = keycodesbuf; 435 names->geometry = geometrybuf; 436 names->symbols = symbolsbuf; 437 (void) strcpy (keycodesbuf, "keycodes/"); 438 (void) strcpy (geometrybuf, "geometry/"); 439 (void) strcpy (symbolsbuf, "symbols/"); 440 441 /* keycodes & geometry */ 442 switch (pKbd->type) { 443 case KB_SUN2: 444 (void) strcat (names->keycodes, "sun(type2)"); 445 (void) strcat (names->geometry, "sun(type2)"); 446 (void) strcat (names->symbols, "us(sun2)"); 447 break; 448 case KB_SUN3: 449 (void) strcat (names->keycodes, "sun(type3)"); 450 (void) strcat (names->geometry, "sun(type3)"); 451 (void) strcat (names->symbols, "us(sun3)"); 452 break; 453 case KB_SUN4: 454 /* First, catch "fully known" models */ 455 switch (pKbd->layout) { 456 case 11: /* type4, Sweden */ 457 (void) strcat (names->geometry, "sun(type4_se)"); 458 (void) strcat (names->keycodes, 459 "sun(type4_se_swapctl)"); 460 (void) strcat (names->symbols, 461 "sun/se(sun4)+se(fixdollar)"); 462 return; 463 break; 464 case 43: /* type5/5c, Sweden */ 465 (void) strcat (names->geometry, "sun(type5c_se)"); 466 (void) strcat (names->keycodes, "sun(type5_se)"); 467 (void) strcat (names->symbols, 468 "sun/se(sun5)+se(fixdollar)"); 469 return; 470 break; 471 case 90: /* "Compact 1", Sweden (???) */ 472 break; /* No specific mapping, yet */ 473 default: 474 break; 475 } 476 477 if (pKbd->layout == 19) { 478 (void) strcat (names->keycodes, "sun(US101A)"); 479 (void) strcat (names->geometry, "pc101-NG"); /* XXX */ 480 (void) strcat (names->symbols, "us(pc101)"); 481 } else if (pKbd->layout < 33) { 482 (void) strcat (names->keycodes, "sun(type4)"); 483 (void) strcat (names->geometry, "sun(type4)"); 484 if (sunSwapLkeys) 485 (void) strcat (names->symbols, "sun/us(sun4ol)"); 486 else 487 (void) strcat (names->symbols, "sun/us(sun4)"); 488 } else { 489 switch (pKbd->layout) { 490 case 33: case 80: /* U.S. */ 491 case 47: case 94: /* Korea */ 492 case 48: case 95: /* Taiwan */ 493 case 49: case 96: /* Japan */ 494 (void) strcat (names->keycodes, "sun(type5)"); 495 (void) strcat (names->geometry, "sun(type5)"); 496 break; 497 case 34: case 81: /* U.S. Unix */ 498 (void) strcat (names->keycodes, "sun(type5)"); 499 (void) strcat (names->geometry, "sun(type5unix)"); 500 break; 501 default: 502 (void) strcat (names->keycodes, "sun(type5_euro)"); 503 (void) strcat (names->geometry, "sun(type5euro)"); 504 } 505 506 if (sunSwapLkeys) 507 (void) strcat (names->symbols, "sun/us(sun5ol)"); 508 else 509 (void) strcat (names->symbols, "sun/us(sun5)"); 510 } 511 break; 512 default: 513 names->keycodes = names->geometry = NULL; 514 break; 515 } 516 517 /* extra symbols */ 518 519 if (pKbd->type == KB_SUN4) { 520 switch (pKbd->layout) { 521 case 4: case 36: case 83: 522 case 5: case 37: case 84: 523 case 6: case 38: case 85: 524 case 8: case 40: case 87: 525 case 9: case 41: case 88: 526 case 10: case 42: case 89: 527/* case 11: case 43: case 90: */ /* handled earlier */ 528 case 12: case 44: case 91: 529 case 13: case 45: case 92: 530 case 14: case 46: case 93: 531 (void) strcat (names->symbols, "+iso9995-3(basic)"); break; 532 } 533 } 534 535 if (pKbd->type == KB_SUN4) { 536 switch (pKbd->layout) { 537 case 0: case 1: case 33: case 34: case 80: case 81: 538 break; 539 case 3: 540 (void) strcat (names->symbols, "+ca"); break; 541 case 4: case 36: case 83: 542 (void) strcat (names->symbols, "+dk"); break; 543 case 5: case 37: case 84: 544 (void) strcat (names->symbols, "+de"); break; 545 case 6: case 38: case 85: 546 (void) strcat (names->symbols, "+it"); break; 547 case 8: case 40: case 87: 548 (void) strcat (names->symbols, "+no"); break; 549 case 9: case 41: case 88: 550 (void) strcat (names->symbols, "+pt"); break; 551 case 10: case 42: case 89: 552 (void) strcat (names->symbols, "+es"); break; 553 /* case 11: case 43: */ /* handled earlier */ 554 case 90: 555 (void) strcat (names->symbols, "+se"); break; 556 case 12: case 44: case 91: 557 (void) strcat (names->symbols, "+fr_CH"); break; 558 case 13: case 45: case 92: 559 (void) strcat (names->symbols, "+de_CH"); break; 560 case 14: case 46: case 93: 561 (void) strcat (names->symbols, "+gb"); break; /* s/b en_UK */ 562 case 52: 563 (void) strcat (names->symbols, "+pl"); break; 564 case 53: 565 (void) strcat (names->symbols, "+cs"); break; 566 case 54: 567 (void) strcat (names->symbols, "+ru"); break; 568#if 0 569 /* don't have symbols defined for these yet, let them default */ 570 case 2: 571 (void) strcat (names->symbols, "+fr_BE"); break; 572 case 7: case 39: case 86: 573 (void) strcat (names->symbols, "+nl"); break; 574 case 50: case 97: 575 (void) strcat (names->symbols, "+fr_CA"); break; 576 case 16: case 47: case 94: 577 (void) strcat (names->symbols, "+ko"); break; 578 case 17: case 48: case 95: 579 (void) strcat (names->symbols, "+tw"); break; 580 case 32: case 49: case 96: 581 (void) strcat (names->symbols, "+jp"); break; 582 case 51: 583 (void) strcat (names->symbols, "+hu"); break; 584#endif 585 /* 586 * by setting the symbols to NULL XKB will use the symbols in 587 * the "default" keymap. 588 */ 589 default: 590 names->symbols = NULL; return; break; 591 } 592 } 593#else 594 rmlvo->rules = "base"; 595 rmlvo->model = "empty"; 596 rmlvo->layout = "empty"; 597 rmlvo->variant = NULL; 598 rmlvo->options = NULL; 599#endif 600} 601 602/*- 603 *----------------------------------------------------------------------- 604 * sunKbdProc -- 605 * Handle the initialization, etc. of a keyboard. 606 * 607 * Results: 608 * None. 609 * 610 *----------------------------------------------------------------------- 611 */ 612 613int 614sunKbdProc(DeviceIntPtr device, int what) 615{ 616 DevicePtr pKeyboard = (DevicePtr) device; 617 sunKbdPrivPtr pPriv; 618 KeybdCtrl* ctrl = &device->kbdfeed->ctrl; 619 XkbRMLVOSet rmlvo; 620 CARD8 workingModMap[MAP_LENGTH]; 621 622 static KeySymsRec *workingKeySyms; 623 624 switch (what) { 625 case DEVICE_INIT: 626 if (pKeyboard != (DevicePtr)sunKeyboardDevice) { 627 ErrorF ("Cannot open non-system keyboard\n"); 628 return (!Success); 629 } 630 631 if (!workingKeySyms) { 632 workingKeySyms = &sunKeySyms[sunKbdPriv.type]; 633 634 if (sunKbdPriv.type == KB_SUN4 && sunSwapLkeys) 635 SwapLKeys(workingKeySyms); 636 637 if (workingKeySyms->minKeyCode < MIN_KEYCODE) { 638 workingKeySyms->minKeyCode += MIN_KEYCODE; 639 workingKeySyms->maxKeyCode += MIN_KEYCODE; 640 } 641 if (workingKeySyms->maxKeyCode > MAX_KEYCODE) 642 workingKeySyms->maxKeyCode = MAX_KEYCODE; 643 644 sunInitModMap(workingKeySyms, workingModMap); 645 } 646 647 pKeyboard->devicePrivate = (void *)&sunKbdPriv; 648 pKeyboard->on = FALSE; 649 650 sunInitKbdNames(&rmlvo, pKeyboard->devicePrivate); 651#if 0 /* XXX needs more work for Xorg xkb */ 652 InitKeyboardDeviceStruct(device, &rmlvo, 653 sunBell, sunKbdCtrl); 654#else 655 XkbSetRulesDflts(&rmlvo); 656 InitKeyboardDeviceStruct(device, NULL, 657 sunBell, sunKbdCtrl); 658 XkbApplyMappingChange(device, workingKeySyms, 659 workingKeySyms->minKeyCode, 660 workingKeySyms->maxKeyCode - 661 workingKeySyms->minKeyCode + 1, 662 workingModMap, serverClient); 663#endif 664 break; 665 666 case DEVICE_ON: 667 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 668 /* 669 * Set the keyboard into "direct" mode and turn on 670 * event translation. 671 */ 672 if (sunChangeKbdTranslation(pPriv->fd,TRUE) == -1) 673 FatalError("Can't set keyboard translation\n"); 674 SetNotifyFd(pPriv->fd, sunKbdHandlerNotify, X_NOTIFY_READ, NULL); 675 pKeyboard->on = TRUE; 676 break; 677 678 case DEVICE_CLOSE: 679 case DEVICE_OFF: 680 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 681 if (pPriv->type == KB_SUN4) { 682 /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */ 683 pPriv->leds = 0; 684 ctrl->leds = 0; 685 SetLights(ctrl, pPriv->fd); 686 } 687 /* 688 * Restore original keyboard directness and translation. 689 */ 690 if (sunChangeKbdTranslation(pPriv->fd,FALSE) == -1) 691 FatalError("Can't reset keyboard translation\n"); 692 RemoveNotifyFd(pPriv->fd); 693 pKeyboard->on = FALSE; 694 break; 695 default: 696 FatalError("Unknown keyboard operation\n"); 697 } 698 return Success; 699} 700 701/*------------------------------------------------------------------------- 702 * sunInitModMap -- 703 * Initialize ModMap per specified KeyMap table. 704 * 705 * Results: 706 * None. 707 * 708 * Side Effects: 709 * None. 710 *-----------------------------------------------------------------------*/ 711static void 712sunInitModMap( 713 const KeySymsRec *KeySyms, /* KeyMap data to set ModMap */ 714 CARD8 *ModMap /* ModMap to be initialized */ 715) 716{ 717 KeySym *k; 718 int i, min, max, width; 719 720 for (i = 0; i < MAP_LENGTH; i++) 721 ModMap[i] = NoSymbol; 722 723 min = KeySyms->minKeyCode; 724 max = KeySyms->maxKeyCode; 725 width = KeySyms->mapWidth; 726 for (i = min, k = KeySyms->map; i < max; i++, k += width) { 727 switch (*k) { 728 729 case XK_Shift_L: 730 case XK_Shift_R: 731 ModMap[i] = ShiftMask; 732 break; 733 734 case XK_Control_L: 735 case XK_Control_R: 736 ModMap[i] = ControlMask; 737 break; 738 739 case XK_Caps_Lock: 740 ModMap[i] = LockMask; 741 break; 742 743 case XK_Alt_L: 744 case XK_Alt_R: 745 ModMap[i] = Alt_Mask; 746 break; 747 748 case XK_Num_Lock: 749 ModMap[i] = Num_Lock_Mask; 750 break; 751 752 case XK_Scroll_Lock: 753 ModMap[i] = ScrollLockMask; 754 break; 755 756 case XK_Meta_L: 757 case XK_Meta_R: 758 ModMap[i] = Meta_Mask; 759 break; 760 761 case SunXK_AltGraph: 762 ModMap[i] = Mode_switch_Mask; 763 break; 764 } 765 } 766} 767 768/*- 769 *----------------------------------------------------------------------- 770 * sunKbdGetEvents -- 771 * Return the events waiting in the wings for the given keyboard. 772 * 773 * Results: 774 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 775 * The number of events contained in the array. 776 * A boolean as to whether more events might be available. 777 * 778 * Side Effects: 779 * None. 780 *----------------------------------------------------------------------- 781 */ 782 783Firm_event * 784sunKbdGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain) 785{ 786 int nBytes; /* number of bytes of events available. */ 787 static Firm_event evBuf[SUN_MAXEVENTS]; /* Buffer for Firm_events */ 788 789 if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) { 790 if (errno == EWOULDBLOCK) { 791 *pNumEvents = 0; 792 *pAgain = FALSE; 793 } else { 794 ErrorF("Reading keyboard"); 795 FatalError ("Could not read the keyboard"); 796 } 797 } else { 798 if (on) { 799 *pNumEvents = nBytes / sizeof (Firm_event); 800 *pAgain = (nBytes == sizeof (evBuf)); 801 } else { 802 *pNumEvents = 0; 803 *pAgain = FALSE; 804 } 805 } 806 return evBuf; 807} 808 809/*- 810 *----------------------------------------------------------------------- 811 * sunKbdEnqueueEvent -- 812 * 813 *----------------------------------------------------------------------- 814 */ 815 816void 817sunKbdEnqueueEvent(DeviceIntPtr device, Firm_event *fe) 818{ 819 BYTE keycode; 820 int type; 821 822 keycode = (fe->id & 0x7f) + MIN_KEYCODE; 823 type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress); 824 QueueKeyboardEvents(device, type, keycode); 825} 826 827 828/*- 829 *----------------------------------------------------------------------- 830 * sunChangeKbdTranslation 831 * Makes operating system calls to set keyboard translation 832 * and direction on or off. 833 * 834 * Results: 835 * -1 if failure, else 0. 836 * 837 * Side Effects: 838 * Changes kernel management of keyboard. 839 * 840 *----------------------------------------------------------------------- 841 */ 842int 843sunChangeKbdTranslation(int fd, Bool makeTranslated) 844{ 845 int tmp; 846#ifndef i386 /* { */ 847 sigset_t hold_mask, old_mask; 848#else /* }{ */ 849 int old_mask; 850#endif /* } */ 851 int toread; 852 char junk[8192]; 853 854#ifndef i386 /* { */ 855 (void) sigfillset(&hold_mask); 856 (void) sigprocmask(SIG_BLOCK, &hold_mask, &old_mask); 857#else /* }{ */ 858 old_mask = sigblock (~0); 859#endif /* } */ 860 sunKbdWait(); 861 if (makeTranslated) { 862 /* 863 * Next set the keyboard into "direct" mode and turn on 864 * event translation. If either of these fails, we can't go 865 * on. 866 */ 867 tmp = 1; 868 if (ioctl (fd, KIOCSDIRECT, &tmp) == -1) { 869 ErrorF("Setting keyboard direct mode"); 870 return -1; 871 } 872 tmp = TR_UNTRANS_EVENT; 873 if (ioctl (fd, KIOCTRANS, &tmp) == -1) { 874 ErrorF("Setting keyboard translation"); 875 ErrorF ("sunChangeKbdTranslation: kbdFd=%d\n", fd); 876 return -1; 877 } 878 } else { 879 /* 880 * Next set the keyboard into "indirect" mode and turn off 881 * event translation. 882 */ 883 tmp = 0; 884 (void)ioctl (fd, KIOCSDIRECT, &tmp); 885 tmp = TR_ASCII; 886 (void)ioctl (fd, KIOCTRANS, &tmp); 887 } 888 if (ioctl (fd, FIONREAD, &toread) != -1 && toread > 0) { 889 while (toread) { 890 tmp = toread; 891 if (toread > sizeof (junk)) 892 tmp = sizeof (junk); 893 (void) read (fd, junk, tmp); 894 toread -= tmp; 895 } 896 } 897#ifndef i386 /* { */ 898 (void) sigprocmask(SIG_SETMASK, &old_mask, NULL); 899#else /* }{ */ 900 sigsetmask (old_mask); 901#endif /* } */ 902 return 0; 903} 904 905/*ARGSUSED*/ 906Bool 907LegalModifier(unsigned int key, DeviceIntPtr pDev) 908{ 909 return TRUE; 910} 911