sunKbd.c revision 381f08b9
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 device; 282 DevicePtr pKeyboard; 283 sunKbdPrivPtr pPriv; 284 285 device = sunKeyboardDevice; 286 if (device != NULL) { 287 pKeyboard = &device->public; 288 if (pKeyboard->on) { 289 pPriv = pKeyboard->devicePrivate; 290 bell(pPriv->fd, duration * 1000); 291 } 292 } 293} 294 295 296#ifdef __sun 297#define XLED_NUM_LOCK 0x1 298#define XLED_COMPOSE 0x4 299#define XLED_SCROLL_LOCK 0x2 300#define XLED_CAPS_LOCK 0x8 301#else 302#define XLED_NUM_LOCK 0x2 303#define XLED_COMPOSE 0x8 304#define XLED_SCROLL_LOCK 0x4 305#define XLED_CAPS_LOCK 0x1 306#endif 307 308static KeyCode 309LookupKeyCode(KeySym keysym, XkbDescPtr xkb, KeySymsPtr syms) 310{ 311 KeyCode i; 312 int ii, index = 0; 313 314 for (i = xkb->min_key_code; i < xkb->max_key_code; i++) 315 for (ii = 0; ii < syms->mapWidth; ii++) 316 if (syms->map[index++] == keysym) 317 return i; 318 return 0; 319} 320 321static void 322pseudoKey(DeviceIntPtr device, Bool down, KeyCode keycode) 323{ 324 int bit; 325 CARD8 modifiers; 326 CARD16 mask; 327 BYTE* kptr; 328 329 kptr = &device->key->down[keycode >> 3]; 330 bit = 1 << (keycode & 7); 331 modifiers = device->key->xkbInfo->desc->map->modmap[keycode]; 332 if (down) { 333 /* fool dix into thinking this key is now "down" */ 334 int i; 335 *kptr |= bit; 336 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 337 if (mask & modifiers) { 338 device->key->modifierKeyCount[i]++; 339 modifiers &= ~mask; 340 } 341 } else { 342 /* fool dix into thinking this key is now "up" */ 343 if (*kptr & bit) { 344 int i; 345 *kptr &= ~bit; 346 for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 347 if (mask & modifiers) { 348 if (--device->key->modifierKeyCount[i] <= 0) { 349 device->key->modifierKeyCount[i] = 0; 350 } 351 modifiers &= ~mask; 352 } 353 } 354 } 355} 356 357static void 358DoLEDs( 359 DeviceIntPtr device, /* Keyboard to alter */ 360 KeybdCtrl* ctrl, 361 sunKbdPrivPtr pPriv 362) 363{ 364 XkbDescPtr xkb; 365 KeySymsPtr syms; 366 367 xkb = device->key->xkbInfo->desc; 368 syms = XkbGetCoreMap(device); 369 if (!syms) 370 return; /* XXX */ 371 372 if ((ctrl->leds & XLED_CAPS_LOCK) && !(pPriv->leds & XLED_CAPS_LOCK)) 373 pseudoKey(device, TRUE, 374 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 375 376 if (!(ctrl->leds & XLED_CAPS_LOCK) && (pPriv->leds & XLED_CAPS_LOCK)) 377 pseudoKey(device, FALSE, 378 LookupKeyCode(XK_Caps_Lock, xkb, syms)); 379 380 if ((ctrl->leds & XLED_NUM_LOCK) && !(pPriv->leds & XLED_NUM_LOCK)) 381 pseudoKey(device, TRUE, 382 LookupKeyCode(XK_Num_Lock, xkb, syms)); 383 384 if (!(ctrl->leds & XLED_NUM_LOCK) && (pPriv->leds & XLED_NUM_LOCK)) 385 pseudoKey(device, FALSE, 386 LookupKeyCode(XK_Num_Lock, xkb, syms)); 387 388 if ((ctrl->leds & XLED_SCROLL_LOCK) && !(pPriv->leds & XLED_SCROLL_LOCK)) 389 pseudoKey(device, TRUE, 390 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 391 392 if (!(ctrl->leds & XLED_SCROLL_LOCK) && (pPriv->leds & XLED_SCROLL_LOCK)) 393 pseudoKey(device, FALSE, 394 LookupKeyCode(XK_Scroll_Lock, xkb, syms)); 395 396 if ((ctrl->leds & XLED_COMPOSE) && !(pPriv->leds & XLED_COMPOSE)) 397 pseudoKey(device, TRUE, 398 LookupKeyCode(SunXK_Compose, xkb, syms)); 399 400 if (!(ctrl->leds & XLED_COMPOSE) && (pPriv->leds & XLED_COMPOSE)) 401 pseudoKey(device, FALSE, 402 LookupKeyCode(SunXK_Compose, xkb, syms)); 403 404 pPriv->leds = ctrl->leds & SUN_LED_MASK; 405 SetLights (ctrl, pPriv->fd); 406 free(syms->map); 407 free(syms); 408} 409 410/*- 411 *----------------------------------------------------------------------- 412 * sunKbdCtrl -- 413 * Alter some of the keyboard control parameters 414 * 415 * Results: 416 * None. 417 * 418 * Side Effects: 419 * Some... 420 * 421 *----------------------------------------------------------------------- 422 */ 423 424static void 425sunKbdCtrl(DeviceIntPtr device, KeybdCtrl* ctrl) 426{ 427 sunKbdPrivPtr pPriv = (sunKbdPrivPtr) device->public.devicePrivate; 428 429 if (pPriv->fd < 0) return; 430 431 if (ctrl->click != pPriv->click) { 432 int kbdClickCmd; 433 434 pPriv->click = ctrl->click; 435 kbdClickCmd = pPriv->click ? KBD_CMD_CLICK : KBD_CMD_NOCLICK; 436 if (ioctl (pPriv->fd, KIOCCMD, &kbdClickCmd) == -1) 437 LogMessage(X_ERROR, "Failed to set keyclick\n"); 438 } 439 if ((pPriv->type == KB_SUN4) && (pPriv->leds != (ctrl->leds & SUN_LED_MASK))) 440 DoLEDs(device, ctrl, pPriv); 441} 442 443/*- 444 *----------------------------------------------------------------------- 445 * sunInitKbdNames -- 446 * Handle the XKB initialization 447 * 448 * Results: 449 * None. 450 * 451 * Comments: 452 * This function needs considerable work, in conjunctions with 453 * the need to add geometry descriptions of Sun Keyboards. 454 * It would also be nice to have #defines for all the keyboard 455 * layouts so that we don't have to have these hard-coded 456 * numbers. 457 * 458 *----------------------------------------------------------------------- 459 */ 460static void 461sunInitKbdNames(XkbRMLVOSet *rmlvo, sunKbdPrivPtr pKbd) 462{ 463#if 0 /* XXX to be revisited later */ 464#ifndef XKBBUFSIZE 465#define XKBBUFSIZE 64 466#endif 467 static char keycodesbuf[XKBBUFSIZE]; 468 static char geometrybuf[XKBBUFSIZE]; 469 static char symbolsbuf[XKBBUFSIZE]; 470 471 names->keymap = NULL; 472 names->compat = "compat/complete"; 473 names->types = "types/complete"; 474 names->keycodes = keycodesbuf; 475 names->geometry = geometrybuf; 476 names->symbols = symbolsbuf; 477 (void) strcpy (keycodesbuf, "keycodes/"); 478 (void) strcpy (geometrybuf, "geometry/"); 479 (void) strcpy (symbolsbuf, "symbols/"); 480 481 /* keycodes & geometry */ 482 switch (pKbd->type) { 483 case KB_SUN2: 484 (void) strcat (names->keycodes, "sun(type2)"); 485 (void) strcat (names->geometry, "sun(type2)"); 486 (void) strcat (names->symbols, "us(sun2)"); 487 break; 488 case KB_SUN3: 489 (void) strcat (names->keycodes, "sun(type3)"); 490 (void) strcat (names->geometry, "sun(type3)"); 491 (void) strcat (names->symbols, "us(sun3)"); 492 break; 493 case KB_SUN4: 494 /* First, catch "fully known" models */ 495 switch (pKbd->layout) { 496 case 11: /* type4, Sweden */ 497 (void) strcat (names->geometry, "sun(type4_se)"); 498 (void) strcat (names->keycodes, 499 "sun(type4_se_swapctl)"); 500 (void) strcat (names->symbols, 501 "sun/se(sun4)+se(fixdollar)"); 502 return; 503 break; 504 case 43: /* type5/5c, Sweden */ 505 (void) strcat (names->geometry, "sun(type5c_se)"); 506 (void) strcat (names->keycodes, "sun(type5_se)"); 507 (void) strcat (names->symbols, 508 "sun/se(sun5)+se(fixdollar)"); 509 return; 510 break; 511 case 90: /* "Compact 1", Sweden (???) */ 512 break; /* No specific mapping, yet */ 513 default: 514 break; 515 } 516 517 if (pKbd->layout == 19) { 518 (void) strcat (names->keycodes, "sun(US101A)"); 519 (void) strcat (names->geometry, "pc101-NG"); /* XXX */ 520 (void) strcat (names->symbols, "us(pc101)"); 521 } else if (pKbd->layout < 33) { 522 (void) strcat (names->keycodes, "sun(type4)"); 523 (void) strcat (names->geometry, "sun(type4)"); 524 if (sunSwapLkeys) 525 (void) strcat (names->symbols, "sun/us(sun4ol)"); 526 else 527 (void) strcat (names->symbols, "sun/us(sun4)"); 528 } else { 529 switch (pKbd->layout) { 530 case 33: case 80: /* U.S. */ 531 case 47: case 94: /* Korea */ 532 case 48: case 95: /* Taiwan */ 533 case 49: case 96: /* Japan */ 534 (void) strcat (names->keycodes, "sun(type5)"); 535 (void) strcat (names->geometry, "sun(type5)"); 536 break; 537 case 34: case 81: /* U.S. Unix */ 538 (void) strcat (names->keycodes, "sun(type5)"); 539 (void) strcat (names->geometry, "sun(type5unix)"); 540 break; 541 default: 542 (void) strcat (names->keycodes, "sun(type5_euro)"); 543 (void) strcat (names->geometry, "sun(type5euro)"); 544 } 545 546 if (sunSwapLkeys) 547 (void) strcat (names->symbols, "sun/us(sun5ol)"); 548 else 549 (void) strcat (names->symbols, "sun/us(sun5)"); 550 } 551 break; 552 default: 553 names->keycodes = names->geometry = NULL; 554 break; 555 } 556 557 /* extra symbols */ 558 559 if (pKbd->type == KB_SUN4) { 560 switch (pKbd->layout) { 561 case 4: case 36: case 83: 562 case 5: case 37: case 84: 563 case 6: case 38: case 85: 564 case 8: case 40: case 87: 565 case 9: case 41: case 88: 566 case 10: case 42: case 89: 567/* case 11: case 43: case 90: */ /* handled earlier */ 568 case 12: case 44: case 91: 569 case 13: case 45: case 92: 570 case 14: case 46: case 93: 571 (void) strcat (names->symbols, "+iso9995-3(basic)"); break; 572 } 573 } 574 575 if (pKbd->type == KB_SUN4) { 576 switch (pKbd->layout) { 577 case 0: case 1: case 33: case 34: case 80: case 81: 578 break; 579 case 3: 580 (void) strcat (names->symbols, "+ca"); break; 581 case 4: case 36: case 83: 582 (void) strcat (names->symbols, "+dk"); break; 583 case 5: case 37: case 84: 584 (void) strcat (names->symbols, "+de"); break; 585 case 6: case 38: case 85: 586 (void) strcat (names->symbols, "+it"); break; 587 case 8: case 40: case 87: 588 (void) strcat (names->symbols, "+no"); break; 589 case 9: case 41: case 88: 590 (void) strcat (names->symbols, "+pt"); break; 591 case 10: case 42: case 89: 592 (void) strcat (names->symbols, "+es"); break; 593 /* case 11: case 43: */ /* handled earlier */ 594 case 90: 595 (void) strcat (names->symbols, "+se"); break; 596 case 12: case 44: case 91: 597 (void) strcat (names->symbols, "+fr_CH"); break; 598 case 13: case 45: case 92: 599 (void) strcat (names->symbols, "+de_CH"); break; 600 case 14: case 46: case 93: 601 (void) strcat (names->symbols, "+gb"); break; /* s/b en_UK */ 602 case 52: 603 (void) strcat (names->symbols, "+pl"); break; 604 case 53: 605 (void) strcat (names->symbols, "+cs"); break; 606 case 54: 607 (void) strcat (names->symbols, "+ru"); break; 608#if 0 609 /* don't have symbols defined for these yet, let them default */ 610 case 2: 611 (void) strcat (names->symbols, "+fr_BE"); break; 612 case 7: case 39: case 86: 613 (void) strcat (names->symbols, "+nl"); break; 614 case 50: case 97: 615 (void) strcat (names->symbols, "+fr_CA"); break; 616 case 16: case 47: case 94: 617 (void) strcat (names->symbols, "+ko"); break; 618 case 17: case 48: case 95: 619 (void) strcat (names->symbols, "+tw"); break; 620 case 32: case 49: case 96: 621 (void) strcat (names->symbols, "+jp"); break; 622 case 51: 623 (void) strcat (names->symbols, "+hu"); break; 624#endif 625 /* 626 * by setting the symbols to NULL XKB will use the symbols in 627 * the "default" keymap. 628 */ 629 default: 630 names->symbols = NULL; return; break; 631 } 632 } 633#else 634 rmlvo->rules = "base"; 635 rmlvo->model = "empty"; 636 rmlvo->layout = "empty"; 637 rmlvo->variant = NULL; 638 rmlvo->options = NULL; 639#endif 640} 641 642static int 643getKbdType(int fd) 644{ 645/* 646 * The Sun 386i has system include files that preclude this pre SunOS 4.1 647 * test for the presence of a type 4 keyboard however it really doesn't 648 * matter since no 386i has ever been shipped with a type 3 keyboard. 649 * SunOS 4.1 no longer needs this kludge. 650 */ 651#if !defined(i386) && !defined(KIOCGKEY) 652#define TYPE4KEYBOARDOVERRIDE 653#endif 654 655 int ii, type; 656 657 for (ii = 0; ii < 3; ii++) { 658 sunKbdWait(); 659 (void)ioctl(fd, KIOCTYPE, &type); 660#ifdef TYPE4KEYBOARDOVERRIDE 661 /* 662 * Magic. Look for a key which is non-existent on a real type 663 * 3 keyboard but does exist on a type 4 keyboard. 664 */ 665 if (type == KB_SUN3) { 666 struct kiockeymap key; 667 668 key.kio_tablemask = 0; 669 key.kio_station = 118; 670 if (ioctl(fd, KIOCGKEY, &key) == -1) { 671 LogMessage(X_ERROR, "ioctl KIOCGKEY\n" ); 672 FatalError("Can't KIOCGKEY on fd %d\n", fd); 673 } 674 if (key.kio_entry != HOLE) 675 type = KB_SUN4; 676 } 677#endif 678 switch (type) { 679 case KB_SUN2: 680 case KB_SUN3: 681 case KB_SUN4: 682 return type; 683 default: 684 sunChangeKbdTranslation(fd, FALSE); 685 continue; 686 } 687 } 688 return -1; 689} 690 691/*- 692 *----------------------------------------------------------------------- 693 * sunKbdProc -- 694 * Handle the initialization, etc. of a keyboard. 695 * 696 * Results: 697 * None. 698 * 699 *----------------------------------------------------------------------- 700 */ 701 702int 703sunKbdProc(DeviceIntPtr device, int what) 704{ 705 DevicePtr pKeyboard = &device->public; 706 sunKbdPrivPtr pPriv; 707 KeybdCtrl* ctrl = &device->kbdfeed->ctrl; 708 XkbRMLVOSet rmlvo; 709 CARD8 workingModMap[MAP_LENGTH]; 710 int type = -1, layout = -1, mapsize; 711 KeySymsPtr keysym; 712 KeySym *map; 713 714 switch (what) { 715 case DEVICE_INIT: 716 pPriv = malloc(sizeof(*pPriv)); 717 if (pPriv == NULL) { 718 LogMessage(X_ERROR, "Cannot allocate private data for keyboard\n"); 719 return !Success; 720 } 721 pPriv->fd = open("/dev/kbd", O_RDWR | O_NONBLOCK, 0); 722 if (pPriv->fd < 0) { 723 LogMessage(X_ERROR, "Cannot open /dev/kbd, error %d\n", errno); 724 free(pPriv); 725 return !Success; 726 } 727 728 type = getKbdType(pPriv->fd); 729 if (type < 0) 730 FatalError("Unsupported keyboard type %d\n", type); 731 732 switch (type) { 733 case KB_SUN2: 734 case KB_SUN3: 735 /* No layout variation */ 736 LogMessage(X_INFO, "Sun type %d Keyboard\n", type); 737 break; 738 case KB_SUN4: 739#define LAYOUT_US5 33 740 (void)ioctl(pPriv->fd, KIOCLAYOUT, &layout); 741 if (layout < 0 || 742 layout > sunMaxLayout || 743 sunType4KeyMaps[layout] == NULL) 744 FatalError("Unsupported keyboard type 4 layout %d\n", layout); 745 /* Type 5 keyboard also treated as Type 4 layout variants */ 746 LogMessage(X_INFO, "Sun type %d Keyboard, layout %d\n", 747 layout >= LAYOUT_US5 ? 5 : 4, layout); 748 break; 749 default: 750 LogMessage(X_INFO, "Unknown keyboard type\n"); 751 break; 752 } 753 754 keysym = &sunKeySyms[type]; 755 mapsize = ((int)keysym->maxKeyCode - (int)keysym->minKeyCode + 1) 756 * keysym->mapWidth * sizeof(keysym->map[0]); 757 map = malloc(mapsize); 758 if (map == NULL) { 759 LogMessage(X_ERROR, "Failed to allocate KeySym map\n"); 760 close(pPriv->fd); 761 free(pPriv); 762 return !Success; 763 } 764 if (type == KB_SUN4) { 765 memcpy(map, sunType4KeyMaps[layout], mapsize); 766 } else { 767 memcpy(map, sunKeySyms[type].map, mapsize); 768 } 769 770 pPriv->type = type; 771 pPriv->layout = layout; 772 pPriv->click = 0; 773 pPriv->leds = (Leds)0; 774 pPriv->keysym.map = map; 775 pPriv->keysym.minKeyCode = keysym->minKeyCode; 776 pPriv->keysym.maxKeyCode = keysym->maxKeyCode; 777 pPriv->keysym.mapWidth = keysym->mapWidth; 778 779 /* sunKbdCtrl() callback refers pKeyboard->devicePrivate */ 780 pKeyboard->devicePrivate = pPriv; 781 pKeyboard->on = FALSE; 782 783 if (type == KB_SUN4 && sunSwapLkeys) { 784 /* This could update pPriv->keysym.map */ 785 SwapLKeys(&pPriv->keysym); 786 } 787 788 if (pPriv->keysym.minKeyCode < MIN_KEYCODE) { 789 pPriv->keysym.minKeyCode += MIN_KEYCODE; 790 pPriv->keysym.maxKeyCode += MIN_KEYCODE; 791 } 792 if (pPriv->keysym.maxKeyCode > MAX_KEYCODE) 793 pPriv->keysym.maxKeyCode = MAX_KEYCODE; 794 795 sunInitModMap(&pPriv->keysym, workingModMap); 796 797 sunInitKbdNames(&rmlvo, pPriv); 798#if 0 /* XXX needs more work for Xorg xkb */ 799 InitKeyboardDeviceStruct(device, &rmlvo, 800 sunBell, sunKbdCtrl); 801#else 802 InitKeyboardDeviceStruct(device, NULL, 803 sunBell, sunKbdCtrl); 804 XkbApplyMappingChange(device, &pPriv->keysym, 805 pPriv->keysym.minKeyCode, 806 pPriv->keysym.maxKeyCode - 807 pPriv->keysym.minKeyCode + 1, 808 workingModMap, serverClient); 809#endif 810 break; 811 812 case DEVICE_ON: 813 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 814 /* 815 * Set the keyboard into "direct" mode and turn on 816 * event translation. 817 */ 818 if (sunChangeKbdTranslation(pPriv->fd, TRUE) == -1) 819 FatalError("Can't set keyboard translation\n"); 820 821 SetNotifyFd(pPriv->fd, sunKbdEvents, X_NOTIFY_READ, device); 822 823 pKeyboard->on = TRUE; 824 break; 825 826 case DEVICE_OFF: 827 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 828 if (pPriv->type == KB_SUN4) { 829 /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */ 830 pPriv->leds = 0; 831 ctrl->leds = 0; 832 SetLights(ctrl, pPriv->fd); 833 } 834 /* 835 * Restore original keyboard directness and translation. 836 */ 837 if (sunChangeKbdTranslation(pPriv->fd, FALSE) == -1) 838 FatalError("Can't reset keyboard translation\n"); 839 RemoveNotifyFd(pPriv->fd); 840 pKeyboard->on = FALSE; 841 break; 842 843 case DEVICE_CLOSE: 844 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 845 free(pPriv->keysym.map); 846 close(pPriv->fd); 847 free(pPriv); 848 pKeyboard->devicePrivate = NULL; 849 break; 850 851 case DEVICE_ABORT: 852 /* 853 * Restore original keyboard directness and translation. 854 */ 855 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 856 (void)sunChangeKbdTranslation(pPriv->fd, FALSE); 857 break; 858 } 859 return Success; 860} 861 862/*------------------------------------------------------------------------- 863 * sunInitModMap -- 864 * Initialize ModMap per specified KeyMap table. 865 * 866 * Results: 867 * None. 868 * 869 * Side Effects: 870 * None. 871 *-----------------------------------------------------------------------*/ 872static void 873sunInitModMap( 874 const KeySymsRec *KeySyms, /* KeyMap data to set ModMap */ 875 CARD8 *ModMap /* ModMap to be initialized */ 876) 877{ 878 KeySym *k; 879 int i, min, max, width; 880 881 for (i = 0; i < MAP_LENGTH; i++) 882 ModMap[i] = NoSymbol; 883 884 min = KeySyms->minKeyCode; 885 max = KeySyms->maxKeyCode; 886 width = KeySyms->mapWidth; 887 for (i = min, k = KeySyms->map; i < max; i++, k += width) { 888 switch (*k) { 889 890 case XK_Shift_L: 891 case XK_Shift_R: 892 ModMap[i] = ShiftMask; 893 break; 894 895 case XK_Control_L: 896 case XK_Control_R: 897 ModMap[i] = ControlMask; 898 break; 899 900 case XK_Caps_Lock: 901 ModMap[i] = LockMask; 902 break; 903 904 case XK_Alt_L: 905 case XK_Alt_R: 906 ModMap[i] = Alt_Mask; 907 break; 908 909 case XK_Num_Lock: 910 ModMap[i] = Num_Lock_Mask; 911 break; 912 913 case XK_Scroll_Lock: 914 ModMap[i] = ScrollLockMask; 915 break; 916 917 case XK_Meta_L: 918 case XK_Meta_R: 919 ModMap[i] = Meta_Mask; 920 break; 921 922 case SunXK_AltGraph: 923 ModMap[i] = Mode_switch_Mask; 924 break; 925 } 926 } 927} 928 929/*- 930 *----------------------------------------------------------------------- 931 * sunKbdGetEvents -- 932 * Return the events waiting in the wings for the given keyboard. 933 * 934 * Results: 935 * Update Firm_event buffer in DeviceIntPtr if events are received. 936 * Return the number of received Firm_events in the buffer. 937 * 938 * Side Effects: 939 * None. 940 *----------------------------------------------------------------------- 941 */ 942 943static int 944sunKbdGetEvents(DeviceIntPtr device) 945{ 946 DevicePtr pKeyboard = &device->public; 947 sunKbdPrivPtr pPriv = pKeyboard->devicePrivate; 948 int nBytes; /* number of bytes of events available. */ 949 int NumEvents = 0; 950 951 nBytes = read(pPriv->fd, pPriv->evbuf, sizeof(pPriv->evbuf)); 952 if (nBytes == -1) { 953 if (errno != EWOULDBLOCK) { 954 LogMessage(X_ERROR, "Unexpected error on reading keyboard\n"); 955 FatalError("Could not read the keyboard"); 956 } 957 } else { 958 NumEvents = nBytes / sizeof(pPriv->evbuf[0]); 959 } 960 return NumEvents; 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