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