OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [keyboard.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.