root/drivers/char/keyb_m68k.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_utf8
  2. process_keycode
  3. put_queue
  4. puts_queue
  5. applkey
  6. enter
  7. caps_toggle
  8. caps_on
  9. show_ptregs
  10. hold
  11. num
  12. bare_num
  13. lastcons
  14. decr_console
  15. incr_console
  16. send_intr
  17. scroll_forw
  18. scroll_back
  19. boot_it
  20. compose
  21. spawn_console
  22. SAK
  23. do_ignore
  24. do_null
  25. do_spec
  26. do_lowercase
  27. do_self
  28. do_dead
  29. handle_diacr
  30. do_cons
  31. do_fn
  32. do_pad
  33. do_cur
  34. do_shift
  35. compute_shiftstate
  36. do_meta
  37. do_ascii
  38. do_lock
  39. do_slock
  40. getledstate
  41. setledstate
  42. register_leds
  43. getleds
  44. kbd_bh
  45. kbd_init

   1 /*
   2  * linux/drivers/char/keyboard.c
   3  *
   4  * Keyboard driver for Linux v0.99 using Latin-1.
   5  *
   6  * Written for linux by Johan Myreen as a translation from
   7  * the assembly version by Linus (with diacriticals added)
   8  *
   9  * Some additional features added by Christoph Niemann (ChN), March 1993
  10  *
  11  * Loadable keymaps by Risto Kankkunen, May 1993
  12  *
  13  * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
  14  * Added decr/incr_console, dynamic keymaps, Unicode support,
  15  * dynamic function/string keys, led setting,  Sept 1994
  16  * `Sticky' modifier keys, 951006.
  17  * 
  18  */
  19 
  20 /*
  21  * modified to provide 'generic' keyboard support by Hamish Macdonald
  22  */
  23 
  24 #include <linux/sched.h>
  25 #include <linux/interrupt.h>
  26 #include <linux/tty.h>
  27 #include <linux/tty_flip.h>
  28 #include <linux/mm.h>
  29 #include <linux/random.h>
  30 
  31 #include <asm/bitops.h>
  32 #include <asm/machdep.h>
  33 
  34 #include "kbd_kern.h"
  35 #include "diacr.h"
  36 #include "vt_kern.h"
  37 
  38 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
  39 
  40 #define KBD_REPORT_ERR
  41 #define KBD_REPORT_UNKN
  42 /* #define KBD_IS_FOCUS_9000 */
  43 
  44 #ifndef KBD_DEFMODE
  45 #define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
  46 #endif
  47 
  48 #ifndef KBD_DEFLEDS
  49 /*
  50  * Some laptops take the 789uiojklm,. keys as number pad when NumLock
  51  * is on. This seems a good reason to start with NumLock off.
  52  */
  53 #define KBD_DEFLEDS 0
  54 #endif
  55 
  56 #ifndef KBD_DEFLOCK
  57 #define KBD_DEFLOCK 0
  58 #endif
  59 
  60 /*
  61  * The default IO slowdown is doing 'inb()'s from 0x61, which should be
  62  * safe. But as that is the keyboard controller chip address, we do our
  63  * slowdowns here by doing short jumps: the keyboard controller should
  64  * be able to keep up
  65  */
  66 #define REALLY_SLOW_IO
  67 #define SLOW_IO_BY_JUMPING
  68 #include <asm/io.h>
  69 #include <asm/system.h>
  70 
  71 extern void poke_blanked_console(void);
  72 extern void ctrl_alt_del(void);
  73 extern void reset_vc(unsigned int new_console);
  74 extern void scrollback(int);
  75 extern void scrollfront(int);
  76 extern int vc_cons_allocated(unsigned int);
  77 
  78 unsigned char kbd_read_mask = 0x01;     /* modified by psaux.c */
  79 
  80 /*
  81  * global state includes the following, and various static variables
  82  * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
  83  * (last_console is now a global variable)
  84  */
  85 
  86 /* shift state counters.. */
  87 static unsigned char k_down[NR_SHIFT] = {0, };
  88 /* keyboard key bitmap */
  89 #define BITS_PER_LONG (8*sizeof(unsigned long))
  90 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
  91 
  92 static int dead_key_next = 0;
  93 /* 
  94  * In order to retrieve the shift_state (for the mouse server), either
  95  * the variable must be global, or a new procedure must be created to 
  96  * return the value. I chose the former way.
  97  */
  98 /*static*/ int shift_state = 0;
  99 static int npadch = -1;                 /* -1 or number assembled on pad */
 100 static unsigned char diacr = 0;
 101 static char rep = 0;                    /* flag telling character repeat */
 102 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 103 static struct tty_struct **ttytab;
 104 static struct kbd_struct *kbd = kbd_table;
 105 static struct tty_struct *tty = NULL;
 106 
 107 extern void compute_shiftstate(void);
 108 
 109 typedef void (*k_hand)(unsigned char value, char up_flag);
 110 typedef void (k_handfn)(unsigned char value, char up_flag);
 111 
 112 static k_handfn
 113         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 114         do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_ignore;
 115 
 116 static k_hand key_handler[16] = {
 117         do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
 118         do_meta, do_ascii, do_lock, do_lowercase, do_slock,
 119         do_ignore, do_ignore, do_ignore
 120 };
 121 
 122 typedef void (*void_fnp)(void);
 123 typedef void (void_fn)(void);
 124 
 125 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
 126         num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
 127         SAK, decr_console, incr_console, spawn_console, bare_num;
 128 
 129 static void_fnp spec_fn_table[] = {
 130         do_null,        enter,          show_ptregs,    show_mem,
 131         show_state,     send_intr,      lastcons,       caps_toggle,
 132         num,            hold,           scroll_forw,    scroll_back,
 133         boot_it,        caps_on,        compose,        SAK,
 134         decr_console,   incr_console,   spawn_console,  bare_num
 135 };
 136 
 137 /* maximum values each key_handler can handle */
 138 const int max_vals[] = {
 139         255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
 140         NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
 141         255, NR_ASCII - 1, NR_LOCK - 1, 255,
 142         NR_LOCK - 1
 143 };
 144 
 145 const int NR_TYPES = SIZE(max_vals);
 146 
 147 static void put_queue(int);
 148 static unsigned char handle_diacr(unsigned char);
 149 
 150 /*
 151  * Many other routines do put_queue, but I think either
 152  * they produce ASCII, or they produce some user-assigned
 153  * string, and in both cases we might assume that it is
 154  * in utf-8 already.
 155  */
 156 void to_utf8(ushort c) {
     /* [previous][next][first][last][top][bottom][index][help] */
 157     if (c < 0x80)
 158         put_queue(c);                   /*  0*******  */
 159     else if (c < 0x800) {
 160         put_queue(0xc0 | (c >> 6));     /*  110***** 10******  */
 161         put_queue(0x80 | (c & 0x3f));
 162     } else {
 163         put_queue(0xe0 | (c >> 12));    /*  1110**** 10****** 10******  */
 164         put_queue(0x80 | ((c >> 6) & 0x3f));
 165         put_queue(0x80 | (c & 0x3f));
 166     }
 167     /* UTF-8 is defined for words of up to 31 bits,
 168        but we need only 16 bits here */
 169 }
 170 
 171 void process_keycode (int keycode)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         char up_flag;                            /* 0 or 0200 */
 174         char raw_mode;
 175 
 176         do_poke_blanked_console = 1;
 177         mark_bh(KEYBOARD_BH);
 178         add_keyboard_randomness(keycode);
 179 
 180         tty = ttytab[fg_console];
 181         kbd = kbd_table + fg_console;
 182         if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
 183                 put_queue(keycode);
 184                 /* we do not return yet, because we want to maintain
 185                    the key_down array, so that we have the correct
 186                    values when finishing RAW mode or when changing VT's */
 187         }
 188 
 189         /*
 190          * At this point the variable `keycode' contains the keycode.
 191          * Note: the keycode must not be 0.
 192          * We keep track of the up/down status of the key, and
 193          * return the keycode if in MEDIUMRAW mode.
 194          */
 195 
 196         up_flag = (keycode & 0200);
 197         keycode &= 0x7f;
 198         if (up_flag) {
 199                 rep = 0;
 200                 if(!clear_bit(keycode, key_down)) {
 201                     /* unexpected, but this can happen:
 202                        maybe this was a key release for a FOCUS 9000
 203                        PF key; if we want to see it, we have to clear
 204                        up_flag */
 205 #ifndef __mc68000__
 206                     if (keycode >= SC_LIM || keycode == 85)
 207                       up_flag = 0;
 208 #endif
 209                 }
 210         } else
 211                 rep = set_bit(keycode, key_down);
 212 
 213         if (raw_mode)
 214                 return;
 215 
 216         if (kbd->kbdmode == VC_MEDIUMRAW) {
 217                 /* soon keycodes will require more than one byte */
 218                 put_queue(keycode + up_flag);
 219                 return;
 220         }
 221 
 222         /*
 223          * Small change in philosophy: earlier we defined repetition by
 224          *       rep = keycode == prev_keycode;
 225          *       prev_keycode = keycode;
 226          * but now by the fact that the depressed key was down already.
 227          * Does this ever make a difference? Yes.
 228          */
 229 
 230         /*
 231          *  Repeat a key only if the input buffers are empty or the
 232          *  characters get echoed locally. This makes key repeat usable
 233          *  with slow applications and under heavy loads.
 234          */
 235         if (!rep ||
 236             (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
 237              (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
 238                 u_short keysym;
 239                 u_char type;
 240 
 241                 /* the XOR below used to be an OR */
 242                 int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
 243                 ushort *key_map = key_maps[shift_final];
 244 
 245                 if (key_map != NULL) {
 246                         keysym = key_map[keycode];
 247                         type = KTYP(keysym);
 248 
 249                         if (type >= 0xf0) {
 250                             type -= 0xf0;
 251                             if (type == KT_LETTER) {
 252                                 type = KT_LATIN;
 253                                 if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
 254                                     key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
 255                                     if (key_map)
 256                                       keysym = key_map[keycode];
 257                                 }
 258                             }
 259                             (*key_handler[type])(keysym & 0xff, up_flag);
 260                             if (type != KT_SLOCK)
 261                               kbd->slockstate = 0;
 262                         } else {
 263                             /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
 264                             if (!up_flag)
 265                               to_utf8(keysym);
 266                         }
 267                 } else {
 268                         /* maybe beep? */
 269                         /* we have at least to update shift_state */
 270 #if 1                   /* how? two almost equivalent choices follow */
 271                         compute_shiftstate();
 272 #else
 273                         keysym = U(plain_map[keycode]);
 274                         type = KTYP(keysym);
 275                         if (type == KT_SHIFT)
 276                           (*key_handler[type])(keysym & 0xff, up_flag);
 277 #endif
 278                 }
 279         }
 280 }
 281 
 282 static void put_queue(int ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284         wake_up(&keypress_wait);
 285         if (tty) {
 286                 tty_insert_flip_char(tty, ch, 0);
 287                 tty_schedule_flip(tty);
 288         }
 289 }
 290 
 291 static void puts_queue(char *cp)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293         wake_up(&keypress_wait);
 294         if (!tty)
 295                 return;
 296 
 297         while (*cp) {
 298                 tty_insert_flip_char(tty, *cp, 0);
 299                 cp++;
 300         }
 301         tty_schedule_flip(tty);
 302 }
 303 
 304 static void applkey(int key, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306         static char buf[] = { 0x1b, 'O', 0x00, 0x00 };
 307 
 308         buf[1] = (mode ? 'O' : '[');
 309         buf[2] = key;
 310         puts_queue(buf);
 311 }
 312 
 313 static void enter(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315         put_queue(13);
 316         if (vc_kbd_mode(kbd,VC_CRLF))
 317                 put_queue(10);
 318 }
 319 
 320 static void caps_toggle(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 321 {
 322         if (rep)
 323                 return;
 324         chg_vc_kbd_led(kbd, VC_CAPSLOCK);
 325 }
 326 
 327 static void caps_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329         if (rep)
 330                 return;
 331         set_vc_kbd_led(kbd, VC_CAPSLOCK);
 332 }
 333 
 334 struct pt_regs *pt_regs;
 335 
 336 static void show_ptregs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338         if (pt_regs)
 339                 show_regs(pt_regs);
 340         return;
 341 }
 342 
 343 static void hold(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 344 {
 345         if (rep || !tty)
 346                 return;
 347 
 348         /*
 349          * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
 350          * these routines are also activated by ^S/^Q.
 351          * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
 352          */
 353         if (tty->stopped)
 354                 start_tty(tty);
 355         else
 356                 stop_tty(tty);
 357 }
 358 
 359 static void num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 360 {
 361         if (vc_kbd_mode(kbd,VC_APPLIC))
 362                 applkey('P', 1);
 363         else
 364                 bare_num();
 365 }
 366 
 367 /*
 368  * Bind this to Shift-NumLock if you work in application keypad mode
 369  * but want to be able to change the NumLock flag.
 370  * Bind this to NumLock if you prefer that the NumLock key always
 371  * changes the NumLock flag.
 372  */
 373 static void bare_num(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 374 {
 375         if (!rep)
 376                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 377 }
 378 
 379 static void lastcons(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 380 {
 381         /* switch to the last used console, ChN */
 382         set_console(last_console);
 383 }
 384 
 385 static void decr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 386 {
 387         int i;
 388  
 389         for (i = fg_console-1; i != fg_console; i--) {
 390                 if (i == -1)
 391                         i = MAX_NR_CONSOLES-1;
 392                 if (vc_cons_allocated(i))
 393                         break;
 394         }
 395         set_console(i);
 396 }
 397 
 398 static void incr_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         int i;
 401 
 402         for (i = fg_console+1; i != fg_console; i++) {
 403                 if (i == MAX_NR_CONSOLES)
 404                         i = 0;
 405                 if (vc_cons_allocated(i))
 406                         break;
 407         }
 408         set_console(i);
 409 }
 410 
 411 static void send_intr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413         if (!tty)
 414                 return;
 415         tty_insert_flip_char(tty, 0, TTY_BREAK);
 416         tty_schedule_flip(tty);
 417 }
 418 
 419 static void scroll_forw(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 420 {
 421         scrollfront(0);
 422 }
 423 
 424 static void scroll_back(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426         scrollback(0);
 427 }
 428 
 429 static void boot_it(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 430 {
 431         ctrl_alt_del();
 432 }
 433 
 434 static void compose(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436         dead_key_next = 1;
 437 }
 438 
 439 int spawnpid, spawnsig;
 440 
 441 static void spawn_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 442 {
 443         if (spawnpid)
 444            if(kill_proc(spawnpid, spawnsig, 1))
 445              spawnpid = 0;
 446 }
 447 
 448 static void SAK(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450         do_SAK(tty);
 451 #if 0
 452         /*
 453          * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
 454          * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
 455          * handling.
 456          * 
 457          * We should do this some day --- the whole point of a secure
 458          * attention key is that it should be guaranteed to always
 459          * work.
 460          */
 461         reset_vc(fg_console);
 462         do_unblank_screen();    /* not in interrupt routine? */
 463 #endif
 464 }
 465 
 466 static void do_ignore(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468 }
 469 
 470 static void do_null()
     /* [previous][next][first][last][top][bottom][index][help] */
 471 {
 472         compute_shiftstate();
 473 }
 474 
 475 static void do_spec(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477         if (up_flag)
 478                 return;
 479         if (value >= SIZE(spec_fn_table))
 480                 return;
 481         spec_fn_table[value]();
 482 }
 483 
 484 static void do_lowercase(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 485 {
 486         printk("keyboard.c: do_lowercase was called - impossible\n");
 487 }
 488 
 489 static void do_self(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 490 {
 491         if (up_flag)
 492                 return;         /* no action, if this is a key release */
 493 
 494         if (diacr)
 495                 value = handle_diacr(value);
 496 
 497         if (dead_key_next) {
 498                 dead_key_next = 0;
 499                 diacr = value;
 500                 return;
 501         }
 502 
 503         put_queue(value);
 504 }
 505 
 506 #define A_GRAVE  '`'
 507 #define A_ACUTE  '\''
 508 #define A_CFLEX  '^'
 509 #define A_TILDE  '~'
 510 #define A_DIAER  '"'
 511 static unsigned char ret_diacr[] =
 512         {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER };
 513 
 514 /* If a dead key pressed twice, output a character corresponding to it, */
 515 /* otherwise just remember the dead key.                                */
 516 
 517 static void do_dead(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 518 {
 519         if (up_flag)
 520                 return;
 521 
 522         value = ret_diacr[value];
 523         if (diacr == value) {   /* pressed twice */
 524                 diacr = 0;
 525                 put_queue(value);
 526                 return;
 527         }
 528         diacr = value;
 529 }
 530 
 531 
 532 /* If space is pressed, return the character corresponding the pending  */
 533 /* dead key, otherwise try to combine the two.                          */
 534 
 535 unsigned char handle_diacr(unsigned char ch)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537         int d = diacr;
 538         int i;
 539 
 540         diacr = 0;
 541         if (ch == ' ')
 542                 return d;
 543 
 544         for (i = 0; i < accent_table_size; i++) {
 545                 if (accent_table[i].diacr == d && accent_table[i].base == ch)
 546                         return accent_table[i].result;
 547         }
 548 
 549         put_queue(d);
 550         return ch;
 551 }
 552 
 553 static void do_cons(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 554 {
 555         if (up_flag)
 556                 return;
 557         set_console(value);
 558 }
 559 
 560 static void do_fn(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 561 {
 562         if (up_flag)
 563                 return;
 564         if (value < SIZE(func_table)) {
 565                 if (func_table[value])
 566                         puts_queue(func_table[value]);
 567         } else
 568                 printk("do_fn called with value=%d\n", value);
 569 }
 570 
 571 static void do_pad(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 572 {
 573         static const char *pad_chars = "0123456789+-*/\015,.?";
 574         static const char *app_map = "pqrstuvwxylSRQMnn?";
 575 
 576         if (up_flag)
 577                 return;         /* no action, if this is a key release */
 578 
 579         /* kludge... shift forces cursor/number keys */
 580         if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) {
 581                 applkey(app_map[value], 1);
 582                 return;
 583         }
 584 
 585         if (!vc_kbd_led(kbd,VC_NUMLOCK))
 586                 switch (value) {
 587                         case KVAL(K_PCOMMA):
 588                         case KVAL(K_PDOT):
 589                                 do_fn(KVAL(K_REMOVE), 0);
 590                                 return;
 591                         case KVAL(K_P0):
 592                                 do_fn(KVAL(K_INSERT), 0);
 593                                 return;
 594                         case KVAL(K_P1):
 595                                 do_fn(KVAL(K_SELECT), 0);
 596                                 return;
 597                         case KVAL(K_P2):
 598                                 do_cur(KVAL(K_DOWN), 0);
 599                                 return;
 600                         case KVAL(K_P3):
 601                                 do_fn(KVAL(K_PGDN), 0);
 602                                 return;
 603                         case KVAL(K_P4):
 604                                 do_cur(KVAL(K_LEFT), 0);
 605                                 return;
 606                         case KVAL(K_P6):
 607                                 do_cur(KVAL(K_RIGHT), 0);
 608                                 return;
 609                         case KVAL(K_P7):
 610                                 do_fn(KVAL(K_FIND), 0);
 611                                 return;
 612                         case KVAL(K_P8):
 613                                 do_cur(KVAL(K_UP), 0);
 614                                 return;
 615                         case KVAL(K_P9):
 616                                 do_fn(KVAL(K_PGUP), 0);
 617                                 return;
 618                         case KVAL(K_P5):
 619                                 applkey('G', vc_kbd_mode(kbd, VC_APPLIC));
 620                                 return;
 621                 }
 622 
 623         put_queue(pad_chars[value]);
 624         if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF))
 625                 put_queue(10);
 626 }
 627 
 628 static void do_cur(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 629 {
 630         static const char *cur_chars = "BDCA";
 631         if (up_flag)
 632                 return;
 633 
 634         applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE));
 635 }
 636 
 637 static void do_shift(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 638 {
 639         int old_state = shift_state;
 640 
 641         if (rep)
 642                 return;
 643 
 644         /* Mimic typewriter:
 645            a CapsShift key acts like Shift but undoes CapsLock */
 646         if (value == KVAL(K_CAPSSHIFT)) {
 647                 value = KVAL(K_SHIFT);
 648                 if (!up_flag)
 649                         clr_vc_kbd_led(kbd, VC_CAPSLOCK);
 650         }
 651 
 652         if (up_flag) {
 653                 /* handle the case that two shift or control
 654                    keys are depressed simultaneously */
 655                 if (k_down[value])
 656                         k_down[value]--;
 657         } else
 658                 k_down[value]++;
 659 
 660         if (k_down[value])
 661                 shift_state |= (1 << value);
 662         else
 663                 shift_state &= ~ (1 << value);
 664 
 665         /* kludge */
 666         if (up_flag && shift_state != old_state && npadch != -1) {
 667                 if (kbd->kbdmode == VC_UNICODE)
 668                   to_utf8(npadch & 0xffff);
 669                 else
 670                   put_queue(npadch & 0xff);
 671                 npadch = -1;
 672         }
 673 }
 674 
 675 /* called after returning from RAW mode or when changing consoles -
 676    recompute k_down[] and shift_state from key_down[] */
 677 /* maybe called when keymap is undefined, so that shiftkey release is seen */
 678 void compute_shiftstate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680         int i, j, k, sym, val;
 681 
 682         shift_state = 0;
 683         for(i=0; i < SIZE(k_down); i++)
 684           k_down[i] = 0;
 685 
 686         for(i=0; i < SIZE(key_down); i++)
 687           if(key_down[i]) {     /* skip this word if not a single bit on */
 688             k = i*BITS_PER_LONG;
 689             for(j=0; j<BITS_PER_LONG; j++,k++)
 690               if(test_bit(k, key_down)) {
 691                 sym = U(plain_map[k]);
 692                 if(KTYP(sym) == KT_SHIFT) {
 693                   val = KVAL(sym);
 694                   if (val == KVAL(K_CAPSSHIFT))
 695                     val = KVAL(K_SHIFT);
 696                   k_down[val]++;
 697                   shift_state |= (1<<val);
 698                 }
 699               }
 700           }
 701 }
 702 
 703 static void do_meta(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 704 {
 705         if (up_flag)
 706                 return;
 707 
 708         if (vc_kbd_mode(kbd, VC_META)) {
 709                 put_queue('\033');
 710                 put_queue(value);
 711         } else
 712                 put_queue(value | 0x80);
 713 }
 714 
 715 static void do_ascii(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 716 {
 717         int base;
 718 
 719         if (up_flag)
 720                 return;
 721 
 722         if (value < 10)    /* decimal input of code, while Alt depressed */
 723             base = 10;
 724         else {       /* hexadecimal input of code, while AltGr depressed */
 725             value -= 10;
 726             base = 16;
 727         }
 728 
 729         if (npadch == -1)
 730                 npadch = value;
 731         else
 732                 npadch = npadch * base + value;
 733 }
 734 
 735 static void do_lock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 736 {
 737         if (up_flag || rep)
 738                 return;
 739         chg_vc_kbd_lock(kbd, value);
 740 }
 741 
 742 static void do_slock(unsigned char value, char up_flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 743 {
 744         if (up_flag || rep)
 745                 return;
 746         chg_vc_kbd_slock(kbd, value);
 747 }
 748 
 749 /*
 750  * The leds display either (i) the status of NumLock, CapsLock, ScrollLock,
 751  * or (ii) whatever pattern of lights people want to show using KDSETLED,
 752  * or (iii) specified bits of specified words in kernel memory.
 753  */
 754 
 755 static unsigned char ledstate = 0xff; /* undefined */
 756 static unsigned char ledioctl;
 757 
 758 unsigned char getledstate(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 759     return ledstate;
 760 }
 761 
 762 void setledstate(struct kbd_struct *kbd, unsigned int led) {
     /* [previous][next][first][last][top][bottom][index][help] */
 763     if (!(led & ~7)) {
 764         ledioctl = led;
 765         kbd->ledmode = LED_SHOW_IOCTL;
 766     } else
 767         kbd->ledmode = LED_SHOW_FLAGS;
 768     set_leds();
 769 }
 770 
 771 static struct ledptr {
 772     unsigned int *addr;
 773     unsigned int mask;
 774     unsigned char valid:1;
 775 } ledptrs[3];
 776 
 777 void register_leds(int console, unsigned int led,
     /* [previous][next][first][last][top][bottom][index][help] */
 778                    unsigned int *addr, unsigned int mask) {
 779     struct kbd_struct *kbd = kbd_table + console;
 780     if (led < 3) {
 781         ledptrs[led].addr = addr;
 782         ledptrs[led].mask = mask;
 783         ledptrs[led].valid = 1;
 784         kbd->ledmode = LED_SHOW_MEM;
 785     } else
 786         kbd->ledmode = LED_SHOW_FLAGS;
 787 }
 788 
 789 static inline unsigned char getleds(void){
     /* [previous][next][first][last][top][bottom][index][help] */
 790     struct kbd_struct *kbd = kbd_table + fg_console;
 791     unsigned char leds;
 792 
 793     if (kbd->ledmode == LED_SHOW_IOCTL)
 794       return ledioctl;
 795     leds = kbd->ledflagstate;
 796     if (kbd->ledmode == LED_SHOW_MEM) {
 797         if (ledptrs[0].valid) {
 798             if (*ledptrs[0].addr & ledptrs[0].mask)
 799               leds |= 1;
 800             else
 801               leds &= ~1;
 802         }
 803         if (ledptrs[1].valid) {
 804             if (*ledptrs[1].addr & ledptrs[1].mask)
 805               leds |= 2;
 806             else
 807               leds &= ~2;
 808         }
 809         if (ledptrs[2].valid) {
 810             if (*ledptrs[2].addr & ledptrs[2].mask)
 811               leds |= 4;
 812             else
 813               leds &= ~4;
 814         }
 815     }
 816     return leds;
 817 }
 818 
 819 /*
 820  * This routine is the bottom half of the keyboard interrupt
 821  * routine, and runs with all interrupts enabled. It does
 822  * console changing, led setting and copy_to_cooked, which can
 823  * take a reasonably long time.
 824  *
 825  * Aside from timing (which isn't really that important for
 826  * keyboard interrupts as they happen often), using the software
 827  * interrupt routines for this thing allows us to easily mask
 828  * this when we don't want any of the above to happen. Not yet
 829  * used, but this allows for easy and efficient race-condition
 830  * prevention later on.
 831  */
 832 static void kbd_bh(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 833 {
 834         unsigned char leds = getleds();
 835 
 836         if (leds != ledstate) {
 837                 ledstate = leds;
 838                 if (mach_kbd_leds)
 839                         mach_kbd_leds(leds);
 840         }
 841 }
 842 
 843 int kbd_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 844 {
 845         int i;
 846         struct kbd_struct kbd0;
 847         extern struct tty_driver console_driver;
 848 
 849         kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
 850         kbd0.ledmode = LED_SHOW_FLAGS;
 851         kbd0.lockstate = KBD_DEFLOCK;
 852         kbd0.slockstate = 0;
 853         kbd0.modeflags = KBD_DEFMODE;
 854         kbd0.kbdmode = VC_XLATE;
 855  
 856         for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
 857                 kbd_table[i] = kbd0;
 858 
 859         ttytab = console_driver.table;
 860 
 861         init_bh(KEYBOARD_BH, kbd_bh);
 862         mark_bh(KEYBOARD_BH);
 863 
 864         mach_keyb_init ();
 865 
 866         return 0;
 867 }

/* [previous][next][first][last][top][bottom][index][help] */