sunKbd.c revision 32b6075a
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 88/* 89 * Data private to any sun keyboard. 90 */ 91typedef struct { 92 int fd; 93 int type; /* Type of keyboard */ 94 int layout; /* The layout of the keyboard */ 95 int click; /* kbd click save state */ 96 Leds leds; /* last known LED state */ 97 KeySymsRec keysym; /* working keysym */ 98} sunKbdPrivRec, *sunKbdPrivPtr; 99 100static void sunKbdEvents(int, int, void *); 101static void sunKbdWait(void); 102static void sunInitModMap(const KeySymsRec *, CARD8 *); 103static Firm_event *sunKbdGetEvents(int, Bool, int *, Bool *); 104static void sunKbdEnqueueEvent(DeviceIntPtr, Firm_event *); 105static void SwapLKeys(KeySymsRec *); 106static void SetLights(KeybdCtrl *, int); 107static KeyCode LookupKeyCode(KeySym, XkbDescPtr, KeySymsPtr); 108static void pseudoKey(DeviceIntPtr, Bool, KeyCode); 109static void DoLEDs(DeviceIntPtr, KeybdCtrl *, sunKbdPrivPtr); 110static int getKbdType(int); 111static int sunChangeKbdTranslation(int, Bool); 112 113DeviceIntPtr sunKeyboardDevice = NULL; 114 115static void 116sunKbdEvents(int fd, int ready, void *data) 117{ 118 int i, numEvents = 0; 119 Bool again = FALSE; 120 Firm_event *events; 121 DeviceIntPtr device = (DeviceIntPtr)data; 122 123 input_lock(); 124 125 do { 126 events = sunKbdGetEvents(fd, device->public.on, &numEvents, &again); 127 for (i = 0; i < numEvents; i++) { 128 sunKbdEnqueueEvent(device, &events[i]); 129 } 130 } while (again); 131 132 input_unlock(); 133} 134 135static void 136sunKbdWait(void) 137{ 138 static struct timeval lastChngKbdTransTv; 139 struct timeval tv; 140 struct timeval lastChngKbdDeltaTv; 141 unsigned int lastChngKbdDelta; 142 143 X_GETTIMEOFDAY(&tv); 144 if (!lastChngKbdTransTv.tv_sec) 145 lastChngKbdTransTv = tv; 146 tvminus(lastChngKbdDeltaTv, tv, lastChngKbdTransTv); 147 lastChngKbdDelta = TVTOMILLI(lastChngKbdDeltaTv); 148 if (lastChngKbdDelta < 750) { 149 unsigned wait; 150 /* 151 * We need to guarantee at least 750 milliseconds between 152 * calls to KIOCTRANS. YUCK! 153 */ 154 wait = (750L - lastChngKbdDelta) * 1000L; 155 usleep (wait); 156 X_GETTIMEOFDAY(&tv); 157 } 158 lastChngKbdTransTv = tv; 159} 160 161static 162void SwapLKeys(KeySymsRec* keysyms) 163{ 164 unsigned int i; 165 KeySym k; 166 167 for (i = 2; i < keysyms->maxKeyCode * keysyms->mapWidth; i++) 168 if (keysyms->map[i] == XK_L1 || 169 keysyms->map[i] == XK_L2 || 170 keysyms->map[i] == XK_L3 || 171 keysyms->map[i] == XK_L4 || 172 keysyms->map[i] == XK_L5 || 173 keysyms->map[i] == XK_L6 || 174 keysyms->map[i] == XK_L7 || 175 keysyms->map[i] == XK_L8 || 176 keysyms->map[i] == XK_L9 || 177 keysyms->map[i] == XK_L10) { 178 /* yes, I could have done a clever two line swap! */ 179 k = keysyms->map[i - 2]; 180 keysyms->map[i - 2] = keysyms->map[i]; 181 keysyms->map[i] = k; 182 } 183} 184 185static void 186SetLights(KeybdCtrl* ctrl, int fd) 187{ 188#ifdef KIOCSLED 189 static unsigned char led_tab[16] = { 190 0, 191#ifdef __sun 192 LED_NUM_LOCK, 193 LED_SCROLL_LOCK, 194 LED_SCROLL_LOCK | LED_NUM_LOCK, 195 LED_COMPOSE, 196 LED_COMPOSE | LED_NUM_LOCK, 197 LED_COMPOSE | LED_SCROLL_LOCK, 198 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK, 199 LED_CAPS_LOCK, 200 LED_CAPS_LOCK | LED_NUM_LOCK, 201 LED_CAPS_LOCK | LED_SCROLL_LOCK, 202 LED_CAPS_LOCK | LED_SCROLL_LOCK | LED_NUM_LOCK, 203 LED_CAPS_LOCK | LED_COMPOSE, 204 LED_CAPS_LOCK | LED_COMPOSE | LED_NUM_LOCK, 205 LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK, 206 LED_CAPS_LOCK | LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK 207#else 208 LED_CAPS_LOCK, 209 LED_NUM_LOCK, 210 LED_NUM_LOCK | LED_CAPS_LOCK, 211 LED_SCROLL_LOCK, 212 LED_SCROLL_LOCK | LED_CAPS_LOCK, 213 LED_SCROLL_LOCK | LED_NUM_LOCK, 214 LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK, 215 LED_COMPOSE, 216 LED_COMPOSE | LED_CAPS_LOCK, 217 LED_COMPOSE | LED_NUM_LOCK, 218 LED_COMPOSE | LED_NUM_LOCK | LED_CAPS_LOCK, 219 LED_COMPOSE | LED_SCROLL_LOCK, 220 LED_COMPOSE | LED_SCROLL_LOCK | LED_CAPS_LOCK, 221 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK, 222 LED_COMPOSE | LED_SCROLL_LOCK | LED_NUM_LOCK | LED_CAPS_LOCK, 223#endif 224 }; 225 if (ioctl (fd, KIOCSLED, (caddr_t)&led_tab[ctrl->leds & SUN_LED_MASK]) == -1) 226 LogMessage(X_ERROR, "Failed to set keyboard lights\n"); 227#endif 228} 229 230 231/*- 232 *----------------------------------------------------------------------- 233 * sunBell -- 234 * Ring the terminal/keyboard bell 235 * 236 * Results: 237 * Ring the keyboard bell for an amount of time proportional to 238 * "loudness." 239 * 240 * Side Effects: 241 * None, really... 242 * 243 *----------------------------------------------------------------------- 244 */ 245 246static void 247bell(int fd, int duration) 248{ 249 int kbdCmd; /* Command to give keyboard */ 250 251 kbdCmd = KBD_CMD_BELL; 252 if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) { 253 LogMessage(X_ERROR, "Failed to activate bell\n"); 254 return; 255 } 256 if (duration) usleep (duration); 257 kbdCmd = KBD_CMD_NOBELL; 258 if (ioctl (fd, KIOCCMD, &kbdCmd) == -1) 259 LogMessage(X_ERROR, "Failed to deactivate bell\n"); 260} 261 262static void 263sunBell(int percent, DeviceIntPtr device, void *ctrl, int unused) 264{ 265 KeybdCtrl* kctrl = (KeybdCtrl*) ctrl; 266 sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate; 267 268 if (percent == 0 || kctrl->bell == 0) 269 return; 270 271 bell (pPriv->fd, kctrl->bell_duration * 1000); 272} 273 274void 275DDXRingBell(int volume, int pitch, int duration) 276{ 277 DeviceIntPtr pKeyboard; 278 sunKbdPrivPtr pPriv; 279 280 pKeyboard = sunKeyboardDevice; 281 if (pKeyboard != NULL) { 282 pPriv = (sunKbdPrivPtr)pKeyboard->public.devicePrivate; 283 bell(pPriv->fd, duration * 1000); 284 } 285} 286 287 288#ifdef __sun 289#define XLED_NUM_LOCK 0x1 290#define XLED_COMPOSE 0x4 291#define XLED_SCROLL_LOCK 0x2 292#define XLED_CAPS_LOCK 0x8 293#else 294#define XLED_NUM_LOCK 0x2 295#define XLED_COMPOSE 0x8 296#define XLED_SCROLL_LOCK 0x4 297#define XLED_CAPS_LOCK 0x1 298#endif 299 300static KeyCode 301LookupKeyCode(KeySym keysym, XkbDescPtr xkb, KeySymsPtr syms) 302{ 303 KeyCode i; 304 int ii, index = 0; 305 306 for (i = xkb->min_key_code; i < xkb->max_key_code; i++) 307 for (ii = 0; ii < syms->mapWidth; ii++) 308 if (syms->map[index++] == keysym) 309 return i; 310 return 0; 311} 312 313static void 314pseudoKey(DeviceIntPtr device, Bool down, KeyCode keycode) 315{ 316 int bit; 317 CARD8 modifiers; 318 CARD16 mask; 319 BYTE* kptr; 320 321 kptr = &device->key->down[keycode >> 3]; 322 bit = 1 << (keycode & 7); 323 modifiers = device->key->xkbInfo->desc->map->modmap[keycode]; 324 if (down) { 325 /* fool dix into thinking this key is now "down" */ 326 int i; 327 *kptr |= bit; 328 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 329 if (mask & modifiers) { 330 device->key->modifierKeyCount[i]++; 331 modifiers &= ~mask; 332 } 333 } else { 334 /* fool dix into thinking this key is now "up" */ 335 if (*kptr & bit) { 336 int i; 337 *kptr &= ~bit; 338 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 339 if (mask & modifiers) { 340 if (--device->key->modifierKeyCount[i] <= 0) { 341 device->key->modifierKeyCount[i] = 0; 342 } 343 modifiers &= ~mask; 344 } 345 } 346 } 347} 348 349static void 350DoLEDs( 351 DeviceIntPtr device, /* Keyboard to alter */ 352 KeybdCtrl* ctrl, 353 sunKbdPrivPtr pPriv 354) 355{ 356 XkbDescPtr xkb; 357 KeySymsPtr syms; 358 359 xkb = device->key->xkbInfo->desc; 360 syms = XkbGetCoreMap(device); 361 if (!syms) 362 return; /* XXX */ 363 364 if ((ctrl->leds & XLED_CAPS_LOCK) && !(pPriv->leds & XLED_CAPS_LOCK)) 365 pseudoKey(device, TRUE, 366 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 367 368 if (!(ctrl->leds & XLED_CAPS_LOCK) && (pPriv->leds & XLED_CAPS_LOCK)) 369 pseudoKey(device, FALSE, 370 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 371 372 if ((ctrl->leds & XLED_NUM_LOCK) && !(pPriv->leds & XLED_NUM_LOCK)) 373 pseudoKey(device, TRUE, 374 LookupKeyCode(XK_Num_Lock, xkb, syms)); 375 376 if (!(ctrl->leds & XLED_NUM_LOCK) && (pPriv->leds & XLED_NUM_LOCK)) 377 pseudoKey(device, FALSE, 378 LookupKeyCode(XK_Num_Lock, xkb, syms)); 379 380 if ((ctrl->leds & XLED_SCROLL_LOCK) && !(pPriv->leds & XLED_SCROLL_LOCK)) 381 pseudoKey(device, TRUE, 382 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 383 384 if (!(ctrl->leds & XLED_SCROLL_LOCK) && (pPriv->leds & XLED_SCROLL_LOCK)) 385 pseudoKey(device, FALSE, 386 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 387 388 if ((ctrl->leds & XLED_COMPOSE) && !(pPriv->leds & XLED_COMPOSE)) 389 pseudoKey(device, TRUE, 390 LookupKeyCode(SunXK_Compose, xkb, syms)); 391 392 if (!(ctrl->leds & XLED_COMPOSE) && (pPriv->leds & XLED_COMPOSE)) 393 pseudoKey(device, FALSE, 394 LookupKeyCode(SunXK_Compose, xkb, syms)); 395 396 pPriv->leds = ctrl->leds & SUN_LED_MASK; 397 SetLights (ctrl, pPriv->fd); 398 free(syms->map); 399 free(syms); 400} 401 402/*- 403 *----------------------------------------------------------------------- 404 * sunKbdCtrl -- 405 * Alter some of the keyboard control parameters 406 * 407 * Results: 408 * None. 409 * 410 * Side Effects: 411 * Some... 412 * 413 *----------------------------------------------------------------------- 414 */ 415 416static void 417sunKbdCtrl(DeviceIntPtr device, KeybdCtrl* ctrl) 418{ 419 sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate; 420 421 if (pPriv->fd < 0) return; 422 423 if (ctrl->click != pPriv->click) { 424 int kbdClickCmd; 425 426 pPriv->click = ctrl->click; 427 kbdClickCmd = pPriv->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK; 428 if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) == -1) 429 LogMessage(X_ERROR, "Failed to set keyclick\n"); 430 } 431 if ((pPriv->type == KB_SUN4) && (pPriv->leds != (ctrl->leds & SUN_LED_MASK))) 432 DoLEDs(device, ctrl, pPriv); 433} 434 435/*- 436 *----------------------------------------------------------------------- 437 * sunInitKbdNames -- 438 * Handle the XKB initialization 439 * 440 * Results: 441 * None. 442 * 443 * Comments: 444 * This function needs considerable work, in conjunctions with 445 * the need to add geometry descriptions of Sun Keyboards. 446 * It would also be nice to have #defines for all the keyboard 447 * layouts so that we don't have to have these hard-coded 448 * numbers. 449 * 450 *----------------------------------------------------------------------- 451 */ 452static void 453sunInitKbdNames(XkbRMLVOSet *rmlvo, sunKbdPrivPtr pKbd) 454{ 455#if 0 /* XXX to be revisited later */ 456#ifndef XKBBUFSIZE 457#define XKBBUFSIZE 64 458#endif 459 static char keycodesbuf[XKBBUFSIZE]; 460 static char geometrybuf[XKBBUFSIZE]; 461 static char symbolsbuf[XKBBUFSIZE]; 462 463 names->keymap = NULL; 464 names->compat = "compat/complete"; 465 names->types = "types/complete"; 466 names->keycodes = keycodesbuf; 467 names->geometry = geometrybuf; 468 names->symbols = symbolsbuf; 469 (void) strcpy (keycodesbuf, "keycodes/"); 470 (void) strcpy (geometrybuf, "geometry/"); 471 (void) strcpy (symbolsbuf, "symbols/"); 472 473 /* keycodes & geometry */ 474 switch (pKbd->type) { 475 case KB_SUN2: 476 (void) strcat (names->keycodes, "sun(type2)"); 477 (void) strcat (names->geometry, "sun(type2)"); 478 (void) strcat (names->symbols, "us(sun2)"); 479 break; 480 case KB_SUN3: 481 (void) strcat (names->keycodes, "sun(type3)"); 482 (void) strcat (names->geometry, "sun(type3)"); 483 (void) strcat (names->symbols, "us(sun3)"); 484 break; 485 case KB_SUN4: 486 /* First, catch "fully known" models */ 487 switch (pKbd->layout) { 488 case 11: /* type4, Sweden */ 489 (void) strcat (names->geometry, "sun(type4_se)"); 490 (void) strcat (names->keycodes, 491 "sun(type4_se_swapctl)"); 492 (void) strcat (names->symbols, 493 "sun/se(sun4)+se(fixdollar)"); 494 return; 495 break; 496 case 43: /* type5/5c, Sweden */ 497 (void) strcat (names->geometry, "sun(type5c_se)"); 498 (void) strcat (names->keycodes, "sun(type5_se)"); 499 (void) strcat (names->symbols, 500 "sun/se(sun5)+se(fixdollar)"); 501 return; 502 break; 503 case 90: /* "Compact 1", Sweden (???) */ 504 break; /* No specific mapping, yet */ 505 default: 506 break; 507 } 508 509 if (pKbd->layout == 19) { 510 (void) strcat (names->keycodes, "sun(US101A)"); 511 (void) strcat (names->geometry, "pc101-NG"); /* XXX */ 512 (void) strcat (names->symbols, "us(pc101)"); 513 } else if (pKbd->layout < 33) { 514 (void) strcat (names->keycodes, "sun(type4)"); 515 (void) strcat (names->geometry, "sun(type4)"); 516 if (sunSwapLkeys) 517 (void) strcat (names->symbols, "sun/us(sun4ol)"); 518 else 519 (void) strcat (names->symbols, "sun/us(sun4)"); 520 } else { 521 switch (pKbd->layout) { 522 case 33: case 80: /* U.S. */ 523 case 47: case 94: /* Korea */ 524 case 48: case 95: /* Taiwan */ 525 case 49: case 96: /* Japan */ 526 (void) strcat (names->keycodes, "sun(type5)"); 527 (void) strcat (names->geometry, "sun(type5)"); 528 break; 529 case 34: case 81: /* U.S. Unix */ 530 (void) strcat (names->keycodes, "sun(type5)"); 531 (void) strcat (names->geometry, "sun(type5unix)"); 532 break; 533 default: 534 (void) strcat (names->keycodes, "sun(type5_euro)"); 535 (void) strcat (names->geometry, "sun(type5euro)"); 536 } 537 538 if (sunSwapLkeys) 539 (void) strcat (names->symbols, "sun/us(sun5ol)"); 540 else 541 (void) strcat (names->symbols, "sun/us(sun5)"); 542 } 543 break; 544 default: 545 names->keycodes = names->geometry = NULL; 546 break; 547 } 548 549 /* extra symbols */ 550 551 if (pKbd->type == KB_SUN4) { 552 switch (pKbd->layout) { 553 case 4: case 36: case 83: 554 case 5: case 37: case 84: 555 case 6: case 38: case 85: 556 case 8: case 40: case 87: 557 case 9: case 41: case 88: 558 case 10: case 42: case 89: 559/* case 11: case 43: case 90: */ /* handled earlier */ 560 case 12: case 44: case 91: 561 case 13: case 45: case 92: 562 case 14: case 46: case 93: 563 (void) strcat (names->symbols, "+iso9995-3(basic)"); break; 564 } 565 } 566 567 if (pKbd->type == KB_SUN4) { 568 switch (pKbd->layout) { 569 case 0: case 1: case 33: case 34: case 80: case 81: 570 break; 571 case 3: 572 (void) strcat (names->symbols, "+ca"); break; 573 case 4: case 36: case 83: 574 (void) strcat (names->symbols, "+dk"); break; 575 case 5: case 37: case 84: 576 (void) strcat (names->symbols, "+de"); break; 577 case 6: case 38: case 85: 578 (void) strcat (names->symbols, "+it"); break; 579 case 8: case 40: case 87: 580 (void) strcat (names->symbols, "+no"); break; 581 case 9: case 41: case 88: 582 (void) strcat (names->symbols, "+pt"); break; 583 case 10: case 42: case 89: 584 (void) strcat (names->symbols, "+es"); break; 585 /* case 11: case 43: */ /* handled earlier */ 586 case 90: 587 (void) strcat (names->symbols, "+se"); break; 588 case 12: case 44: case 91: 589 (void) strcat (names->symbols, "+fr_CH"); break; 590 case 13: case 45: case 92: 591 (void) strcat (names->symbols, "+de_CH"); break; 592 case 14: case 46: case 93: 593 (void) strcat (names->symbols, "+gb"); break; /* s/b en_UK */ 594 case 52: 595 (void) strcat (names->symbols, "+pl"); break; 596 case 53: 597 (void) strcat (names->symbols, "+cs"); break; 598 case 54: 599 (void) strcat (names->symbols, "+ru"); break; 600#if 0 601 /* don't have symbols defined for these yet, let them default */ 602 case 2: 603 (void) strcat (names->symbols, "+fr_BE"); break; 604 case 7: case 39: case 86: 605 (void) strcat (names->symbols, "+nl"); break; 606 case 50: case 97: 607 (void) strcat (names->symbols, "+fr_CA"); break; 608 case 16: case 47: case 94: 609 (void) strcat (names->symbols, "+ko"); break; 610 case 17: case 48: case 95: 611 (void) strcat (names->symbols, "+tw"); break; 612 case 32: case 49: case 96: 613 (void) strcat (names->symbols, "+jp"); break; 614 case 51: 615 (void) strcat (names->symbols, "+hu"); break; 616#endif 617 /* 618 * by setting the symbols to NULL XKB will use the symbols in 619 * the "default" keymap. 620 */ 621 default: 622 names->symbols = NULL; return; break; 623 } 624 } 625#else 626 rmlvo->rules = "base"; 627 rmlvo->model = "empty"; 628 rmlvo->layout = "empty"; 629 rmlvo->variant = NULL; 630 rmlvo->options = NULL; 631#endif 632} 633 634static int 635getKbdType(int fd) 636{ 637/* 638 * The Sun 386i has system include files that preclude this pre SunOS 4.1 639 * test for the presence of a type 4 keyboard however it really doesn't 640 * matter since no 386i has ever been shipped with a type 3 keyboard. 641 * SunOS 4.1 no longer needs this kludge. 642 */ 643#if !defined(i386) && !defined(KIOCGKEY) 644#define TYPE4KEYBOARDOVERRIDE 645#endif 646 647 int ii, type; 648 649 for (ii = 0; ii < 3; ii++) { 650 sunKbdWait(); 651 (void)ioctl(fd, KIOCTYPE, &type); 652#ifdef TYPE4KEYBOARDOVERRIDE 653 /* 654 * Magic. Look for a key which is non-existent on a real type 655 * 3 keyboard but does exist on a type 4 keyboard. 656 */ 657 if (type == KB_SUN3) { 658 struct kiockeymap key; 659 660 key.kio_tablemask = 0; 661 key.kio_station = 118; 662 if (ioctl(fd, KIOCGKEY, &key) == -1) { 663 LogMessage(X_ERROR, "ioctl KIOCGKEY\n" ); 664 FatalError("Can't KIOCGKEY on fd %d\n", fd); 665 } 666 if (key.kio_entry != HOLE) 667 type = KB_SUN4; 668 } 669#endif 670 switch (type) { 671 case KB_SUN2: 672 case KB_SUN3: 673 case KB_SUN4: 674 return type; 675 default: 676 sunChangeKbdTranslation(fd, FALSE); 677 continue; 678 } 679 } 680 return -1; 681} 682 683/*- 684 *----------------------------------------------------------------------- 685 * sunKbdProc -- 686 * Handle the initialization, etc. of a keyboard. 687 * 688 * Results: 689 * None. 690 * 691 *----------------------------------------------------------------------- 692 */ 693 694int 695sunKbdProc(DeviceIntPtr device, int what) 696{ 697 DevicePtr pKeyboard = &device->public; 698 sunKbdPrivPtr pPriv; 699 KeybdCtrl* ctrl = &device->kbdfeed->ctrl; 700 XkbRMLVOSet rmlvo; 701 CARD8 workingModMap[MAP_LENGTH]; 702 int type = -1, layout = -1, mapsize; 703 KeySymsPtr keysym; 704 KeySym *map; 705 706 switch (what) { 707 case DEVICE_INIT: 708 pPriv = malloc(sizeof(*pPriv)); 709 if (pPriv == NULL) { 710 LogMessage(X_ERROR, "Cannot allocate private data for keyboard\n"); 711 return !Success; 712 } 713 pPriv->fd = open("/dev/kbd", O_RDWR | O_NONBLOCK, 0); 714 if (pPriv->fd < 0) { 715 LogMessage(X_ERROR, "Cannot open /dev/kbd, error %d\n", errno); 716 free(pPriv); 717 return !Success; 718 } 719 720 type = getKbdType(pPriv->fd); 721 if (type < 0) 722 FatalError("Unsupported keyboard type %d\n", type); 723 724 switch (type) { 725 case KB_SUN2: 726 case KB_SUN3: 727 /* No layout variation */ 728 LogMessage(X_INFO, "Sun type %d Keyboard\n", type); 729 break; 730 case KB_SUN4: 731#define LAYOUT_US5 33 732 (void)ioctl(pPriv->fd, KIOCLAYOUT, &layout); 733 if (layout < 0 || 734 layout > sunMaxLayout || 735 sunType4KeyMaps[layout] == NULL) 736 FatalError("Unsupported keyboard type 4 layout %d\n", layout); 737 /* Type 5 keyboard also treated as Type 4 layout variants */ 738 LogMessage(X_INFO, "Sun type %d Keyboard, layout %d\n", 739 layout >= LAYOUT_US5 ? 5 : 4, layout); 740 break; 741 default: 742 LogMessage(X_INFO, "Unknown keyboard type\n"); 743 break; 744 } 745 746 keysym = &sunKeySyms[type]; 747 mapsize = ((int)keysym->maxKeyCode - (int)keysym->minKeyCode + 1) 748 * keysym->mapWidth * sizeof(keysym->map[0]); 749 map = malloc(mapsize); 750 if (map == NULL) { 751 LogMessage(X_ERROR, "Failed to allocate KeySym map\n"); 752 close(pPriv->fd); 753 free(pPriv); 754 return !Success; 755 } 756 if (type == KB_SUN4) { 757 memcpy(map, sunType4KeyMaps[layout], mapsize); 758 } else { 759 memcpy(map, sunKeySyms[type].map, mapsize); 760 } 761 762 pPriv->type = type; 763 pPriv->layout = layout; 764 pPriv->click = 0; 765 pPriv->leds = (Leds)0; 766 pPriv->keysym.map = map; 767 pPriv->keysym.minKeyCode = keysym->minKeyCode; 768 pPriv->keysym.maxKeyCode = keysym->maxKeyCode; 769 pPriv->keysym.mapWidth = keysym->mapWidth; 770 771 /* sunKbdCtrl() callback refers pKeyboard->devicePrivate */ 772 pKeyboard->devicePrivate = pPriv; 773 pKeyboard->on = FALSE; 774 775 if (type == KB_SUN4 && sunSwapLkeys) { 776 /* This could update pPriv->keysym.map */ 777 SwapLKeys(&pPriv->keysym); 778 } 779 780 if (pPriv->keysym.minKeyCode < MIN_KEYCODE) { 781 pPriv->keysym.minKeyCode += MIN_KEYCODE; 782 pPriv->keysym.maxKeyCode += MIN_KEYCODE; 783 } 784 if (pPriv->keysym.maxKeyCode > MAX_KEYCODE) 785 pPriv->keysym.maxKeyCode = MAX_KEYCODE; 786 787 sunInitModMap(&pPriv->keysym, workingModMap); 788 789 sunInitKbdNames(&rmlvo, pPriv); 790#if 0 /* XXX needs more work for Xorg xkb */ 791 InitKeyboardDeviceStruct(device, &rmlvo, 792 sunBell, sunKbdCtrl); 793#else 794 XkbSetRulesDflts(&rmlvo); 795 InitKeyboardDeviceStruct(device, NULL, 796 sunBell, sunKbdCtrl); 797 XkbApplyMappingChange(device, &pPriv->keysym, 798 pPriv->keysym.minKeyCode, 799 pPriv->keysym.maxKeyCode - 800 pPriv->keysym.minKeyCode + 1, 801 workingModMap, serverClient); 802#endif 803 break; 804 805 case DEVICE_ON: 806 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 807 /* 808 * Set the keyboard into "direct" mode and turn on 809 * event translation. 810 */ 811 if (sunChangeKbdTranslation(pPriv->fd, TRUE) == -1) 812 FatalError("Can't set keyboard translation\n"); 813 814 SetNotifyFd(pPriv->fd, sunKbdEvents, X_NOTIFY_READ, device); 815 816 pKeyboard->on = TRUE; 817 break; 818 819 case DEVICE_OFF: 820 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 821 if (pPriv->type == KB_SUN4) { 822 /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */ 823 pPriv->leds = 0; 824 ctrl->leds = 0; 825 SetLights(ctrl, pPriv->fd); 826 } 827 /* 828 * Restore original keyboard directness and translation. 829 */ 830 if (sunChangeKbdTranslation(pPriv->fd, FALSE) == -1) 831 FatalError("Can't reset keyboard translation\n"); 832 RemoveNotifyFd(pPriv->fd); 833 pKeyboard->on = FALSE; 834 break; 835 836 case DEVICE_CLOSE: 837 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 838 free(pPriv->keysym.map); 839 close(pPriv->fd); 840 free(pPriv); 841 pKeyboard->devicePrivate = NULL; 842 break; 843 844 case DEVICE_ABORT: 845 /* 846 * Restore original keyboard directness and translation. 847 */ 848 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 849 (void)sunChangeKbdTranslation(pPriv->fd, FALSE); 850 break; 851 } 852 return Success; 853} 854 855/*------------------------------------------------------------------------- 856 * sunInitModMap -- 857 * Initialize ModMap per specified KeyMap table. 858 * 859 * Results: 860 * None. 861 * 862 * Side Effects: 863 * None. 864 *-----------------------------------------------------------------------*/ 865static void 866sunInitModMap( 867 const KeySymsRec *KeySyms, /* KeyMap data to set ModMap */ 868 CARD8 *ModMap /* ModMap to be initialized */ 869) 870{ 871 KeySym *k; 872 int i, min, max, width; 873 874 for (i = 0; i < MAP_LENGTH; i++) 875 ModMap[i] = NoSymbol; 876 877 min = KeySyms->minKeyCode; 878 max = KeySyms->maxKeyCode; 879 width = KeySyms->mapWidth; 880 for (i = min, k = KeySyms->map; i < max; i++, k += width) { 881 switch (*k) { 882 883 case XK_Shift_L: 884 case XK_Shift_R: 885 ModMap[i] = ShiftMask; 886 break; 887 888 case XK_Control_L: 889 case XK_Control_R: 890 ModMap[i] = ControlMask; 891 break; 892 893 case XK_Caps_Lock: 894 ModMap[i] = LockMask; 895 break; 896 897 case XK_Alt_L: 898 case XK_Alt_R: 899 ModMap[i] = Alt_Mask; 900 break; 901 902 case XK_Num_Lock: 903 ModMap[i] = Num_Lock_Mask; 904 break; 905 906 case XK_Scroll_Lock: 907 ModMap[i] = ScrollLockMask; 908 break; 909 910 case XK_Meta_L: 911 case XK_Meta_R: 912 ModMap[i] = Meta_Mask; 913 break; 914 915 case SunXK_AltGraph: 916 ModMap[i] = Mode_switch_Mask; 917 break; 918 } 919 } 920} 921 922/*- 923 *----------------------------------------------------------------------- 924 * sunKbdGetEvents -- 925 * Return the events waiting in the wings for the given keyboard. 926 * 927 * Results: 928 * A pointer to an array of Firm_events or (Firm_event *)0 if no events 929 * The number of events contained in the array. 930 * A boolean as to whether more events might be available. 931 * 932 * Side Effects: 933 * None. 934 *----------------------------------------------------------------------- 935 */ 936 937static Firm_event * 938sunKbdGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain) 939{ 940 int nBytes; /* number of bytes of events available. */ 941 static Firm_event evBuf[SUN_MAXEVENTS]; /* Buffer for Firm_events */ 942 943 if ((nBytes = read (fd, evBuf, sizeof(evBuf))) == -1) { 944 if (errno == EWOULDBLOCK) { 945 *pNumEvents = 0; 946 *pAgain = FALSE; 947 } else { 948 ErrorF("Reading keyboard\n"); 949 FatalError ("Could not read the keyboard"); 950 } 951 } else { 952 if (on) { 953 *pNumEvents = nBytes / sizeof (Firm_event); 954 *pAgain = (nBytes == sizeof (evBuf)); 955 } else { 956 *pNumEvents = 0; 957 *pAgain = FALSE; 958 } 959 } 960 return evBuf; 961} 962 963/*- 964 *----------------------------------------------------------------------- 965 * sunKbdEnqueueEvent -- 966 * 967 *----------------------------------------------------------------------- 968 */ 969 970static void 971sunKbdEnqueueEvent(DeviceIntPtr device, Firm_event *fe) 972{ 973 BYTE keycode; 974 int type; 975 976 keycode = (fe->id & 0x7f) + MIN_KEYCODE; 977 type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress); 978 QueueKeyboardEvents(device, type, keycode); 979} 980 981 982/*- 983 *----------------------------------------------------------------------- 984 * sunChangeKbdTranslation 985 * Makes operating system calls to set keyboard translation 986 * and direction on or off. 987 * 988 * Results: 989 * -1 if failure, else 0. 990 * 991 * Side Effects: 992 * Changes kernel management of keyboard. 993 * 994 *----------------------------------------------------------------------- 995 */ 996static int 997sunChangeKbdTranslation(int fd, Bool makeTranslated) 998{ 999 int tmp; 1000#ifndef i386 /* { */ 1001 sigset_t hold_mask, old_mask; 1002#else /* }{ */ 1003 int old_mask; 1004#endif /* } */ 1005 int toread; 1006 char junk[8192]; 1007 1008#ifndef i386 /* { */ 1009 (void) sigfillset(&hold_mask); 1010 (void) sigprocmask(SIG_BLOCK, &hold_mask, &old_mask); 1011#else /* }{ */ 1012 old_mask = sigblock (~0); 1013#endif /* } */ 1014 sunKbdWait(); 1015 if (makeTranslated) { 1016 /* 1017 * Next set the keyboard into "direct" mode and turn on 1018 * event translation. If either of these fails, we can't go 1019 * on. 1020 */ 1021 tmp = 1; 1022 if (ioctl (fd, KIOCSDIRECT, &tmp) == -1) { 1023 ErrorF("Setting keyboard direct mode\n"); 1024 return -1; 1025 } 1026 tmp = TR_UNTRANS_EVENT; 1027 if (ioctl (fd, KIOCTRANS, &tmp) == -1) { 1028 ErrorF("Setting keyboard translation\n"); 1029 ErrorF ("sunChangeKbdTranslation: kbdFd=%d\n", fd); 1030 return -1; 1031 } 1032 } else { 1033 /* 1034 * Next set the keyboard into "indirect" mode and turn off 1035 * event translation. 1036 */ 1037 tmp = 0; 1038 (void)ioctl (fd, KIOCSDIRECT, &tmp); 1039 tmp = TR_ASCII; 1040 (void)ioctl (fd, KIOCTRANS, &tmp); 1041 } 1042 if (ioctl (fd, FIONREAD, &toread) != -1 && toread > 0) { 1043 while (toread) { 1044 tmp = toread; 1045 if (toread > sizeof (junk)) 1046 tmp = sizeof (junk); 1047 (void) read (fd, junk, tmp); 1048 toread -= tmp; 1049 } 1050 } 1051#ifndef i386 /* { */ 1052 (void) sigprocmask(SIG_SETMASK, &old_mask, NULL); 1053#else /* }{ */ 1054 sigsetmask (old_mask); 1055#endif /* } */ 1056 return 0; 1057} 1058