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