sunKbd.c revision f8338865
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 XkbSetRulesDflts(&rmlvo); 803 InitKeyboardDeviceStruct(device, NULL, 804 sunBell, sunKbdCtrl); 805 XkbApplyMappingChange(device, &pPriv->keysym, 806 pPriv->keysym.minKeyCode, 807 pPriv->keysym.maxKeyCode - 808 pPriv->keysym.minKeyCode + 1, 809 workingModMap, serverClient); 810#endif 811 break; 812 813 case DEVICE_ON: 814 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 815 /* 816 * Set the keyboard into "direct" mode and turn on 817 * event translation. 818 */ 819 if (sunChangeKbdTranslation(pPriv->fd, TRUE) == -1) 820 FatalError("Can't set keyboard translation\n"); 821 822 SetNotifyFd(pPriv->fd, sunKbdEvents, X_NOTIFY_READ, device); 823 824 pKeyboard->on = TRUE; 825 break; 826 827 case DEVICE_OFF: 828 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 829 if (pPriv->type == KB_SUN4) { 830 /* dumb bug in Sun's keyboard! Turn off LEDS before resetting */ 831 pPriv->leds = 0; 832 ctrl->leds = 0; 833 SetLights(ctrl, pPriv->fd); 834 } 835 /* 836 * Restore original keyboard directness and translation. 837 */ 838 if (sunChangeKbdTranslation(pPriv->fd, FALSE) == -1) 839 FatalError("Can't reset keyboard translation\n"); 840 RemoveNotifyFd(pPriv->fd); 841 pKeyboard->on = FALSE; 842 break; 843 844 case DEVICE_CLOSE: 845 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 846 free(pPriv->keysym.map); 847 close(pPriv->fd); 848 free(pPriv); 849 pKeyboard->devicePrivate = NULL; 850 break; 851 852 case DEVICE_ABORT: 853 /* 854 * Restore original keyboard directness and translation. 855 */ 856 pPriv = (sunKbdPrivPtr)pKeyboard->devicePrivate; 857 (void)sunChangeKbdTranslation(pPriv->fd, FALSE); 858 break; 859 } 860 return Success; 861} 862 863/*------------------------------------------------------------------------- 864 * sunInitModMap -- 865 * Initialize ModMap per specified KeyMap table. 866 * 867 * Results: 868 * None. 869 * 870 * Side Effects: 871 * None. 872 *-----------------------------------------------------------------------*/ 873static void 874sunInitModMap( 875 const KeySymsRec *KeySyms, /* KeyMap data to set ModMap */ 876 CARD8 *ModMap /* ModMap to be initialized */ 877) 878{ 879 KeySym *k; 880 int i, min, max, width; 881 882 for (i = 0; i < MAP_LENGTH; i++) 883 ModMap[i] = NoSymbol; 884 885 min = KeySyms->minKeyCode; 886 max = KeySyms->maxKeyCode; 887 width = KeySyms->mapWidth; 888 for (i = min, k = KeySyms->map; i < max; i++, k += width) { 889 switch (*k) { 890 891 case XK_Shift_L: 892 case XK_Shift_R: 893 ModMap[i] = ShiftMask; 894 break; 895 896 case XK_Control_L: 897 case XK_Control_R: 898 ModMap[i] = ControlMask; 899 break; 900 901 case XK_Caps_Lock: 902 ModMap[i] = LockMask; 903 break; 904 905 case XK_Alt_L: 906 case XK_Alt_R: 907 ModMap[i] = Alt_Mask; 908 break; 909 910 case XK_Num_Lock: 911 ModMap[i] = Num_Lock_Mask; 912 break; 913 914 case XK_Scroll_Lock: 915 ModMap[i] = ScrollLockMask; 916 break; 917 918 case XK_Meta_L: 919 case XK_Meta_R: 920 ModMap[i] = Meta_Mask; 921 break; 922 923 case SunXK_AltGraph: 924 ModMap[i] = Mode_switch_Mask; 925 break; 926 } 927 } 928} 929 930/*- 931 *----------------------------------------------------------------------- 932 * sunKbdGetEvents -- 933 * Return the events waiting in the wings for the given keyboard. 934 * 935 * Results: 936 * Update Firm_event buffer in DeviceIntPtr if events are received. 937 * Return the number of received Firm_events in the buffer. 938 * 939 * Side Effects: 940 * None. 941 *----------------------------------------------------------------------- 942 */ 943 944static int 945sunKbdGetEvents(DeviceIntPtr device) 946{ 947 DevicePtr pKeyboard = &device->public; 948 sunKbdPrivPtr pPriv = pKeyboard->devicePrivate; 949 int nBytes; /* number of bytes of events available. */ 950 int NumEvents = 0; 951 952 nBytes = read(pPriv->fd, pPriv->evbuf, sizeof(pPriv->evbuf)); 953 if (nBytes == -1) { 954 if (errno != EWOULDBLOCK) { 955 LogMessage(X_ERROR, "Unexpected error on reading keyboard\n"); 956 FatalError("Could not read the keyboard"); 957 } 958 } else { 959 NumEvents = nBytes / sizeof(pPriv->evbuf[0]); 960 } 961 return NumEvents; 962} 963 964/*- 965 *----------------------------------------------------------------------- 966 * sunKbdEnqueueEvent -- 967 * 968 *----------------------------------------------------------------------- 969 */ 970 971static void 972sunKbdEnqueueEvent(DeviceIntPtr device, Firm_event *fe) 973{ 974 BYTE keycode; 975 int type; 976 977 keycode = (fe->id & 0x7f) + MIN_KEYCODE; 978 type = ((fe->value == VKEY_UP) ? KeyRelease : KeyPress); 979 QueueKeyboardEvents(device, type, keycode); 980} 981 982 983/*- 984 *----------------------------------------------------------------------- 985 * sunChangeKbdTranslation 986 * Makes operating system calls to set keyboard translation 987 * and direction on or off. 988 * 989 * Results: 990 * -1 if failure, else 0. 991 * 992 * Side Effects: 993 * Changes kernel management of keyboard. 994 * 995 *----------------------------------------------------------------------- 996 */ 997static int 998sunChangeKbdTranslation(int fd, Bool makeTranslated) 999{ 1000 int tmp; 1001#ifndef i386 /* { */ 1002 sigset_t hold_mask, old_mask; 1003#else /* }{ */ 1004 int old_mask; 1005#endif /* } */ 1006 int toread; 1007 char junk[8192]; 1008 1009#ifndef i386 /* { */ 1010 (void) sigfillset(&hold_mask); 1011 (void) sigprocmask(SIG_BLOCK, &hold_mask, &old_mask); 1012#else /* }{ */ 1013 old_mask = sigblock (~0); 1014#endif /* } */ 1015 sunKbdWait(); 1016 if (makeTranslated) { 1017 /* 1018 * Next set the keyboard into "direct" mode and turn on 1019 * event translation. If either of these fails, we can't go 1020 * on. 1021 */ 1022 tmp = 1; 1023 if (ioctl (fd, KIOCSDIRECT, &tmp) == -1) { 1024 ErrorF("Setting keyboard direct mode\n"); 1025 return -1; 1026 } 1027 tmp = TR_UNTRANS_EVENT; 1028 if (ioctl (fd, KIOCTRANS, &tmp) == -1) { 1029 ErrorF("Setting keyboard translation\n"); 1030 ErrorF ("sunChangeKbdTranslation: kbdFd=%d\n", fd); 1031 return -1; 1032 } 1033 } else { 1034 /* 1035 * Next set the keyboard into "indirect" mode and turn off 1036 * event translation. 1037 */ 1038 tmp = 0; 1039 (void)ioctl (fd, KIOCSDIRECT, &tmp); 1040 tmp = TR_ASCII; 1041 (void)ioctl (fd, KIOCTRANS, &tmp); 1042 } 1043 if (ioctl (fd, FIONREAD, &toread) != -1 && toread > 0) { 1044 while (toread) { 1045 tmp = toread; 1046 if (toread > sizeof (junk)) 1047 tmp = sizeof (junk); 1048 (void) read (fd, junk, tmp); 1049 toread -= tmp; 1050 } 1051 } 1052#ifndef i386 /* { */ 1053 (void) sigprocmask(SIG_SETMASK, &old_mask, NULL); 1054#else /* }{ */ 1055 sigsetmask (old_mask); 1056#endif /* } */ 1057 return 0; 1058} 1059