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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [char/] [keyboard.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * linux/arch/arm/drivers/block/keyboard.c
3
 *
4
 * Keyboard driver for Linux 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
 * Majorly altered for use with arm Russell King (rmk@ecs.soton.ac.uk)
19
 *  The low-level keyboard driver is now separate.
20
 *  Interfaces:
21
 *    Driver supplies:
22
 *      kbd_drv_init    - initialise keyboard driver proper
23
 *      kbd_drv_setleds - set leds on keyboard
24
 *    Driver uses:
25
 *      kbd_keyboardkey - process a keypress/release
26
 *      kbd_reset       - reset keyboard down array
27
 *      kbd_setregs     - set regs for scroll-lock debug
28
 */
29
 
30
#include <linux/sched.h>
31
#include <linux/interrupt.h>
32
#include <linux/tty.h>
33
#include <linux/tty_flip.h>
34
#include <linux/mm.h>
35
#include <linux/malloc.h>
36
#include <linux/ptrace.h>
37
#include <linux/signal.h>
38
#include <linux/timer.h>
39
#include <linux/random.h>
40
#include <linux/ctype.h>
41
 
42
#include <asm/bitops.h>
43
#include <asm/system.h>
44
#include <asm/irq.h>
45
#include <asm/segment.h>
46
 
47
#include "kbd_kern.h"
48
#include "diacr.h"
49
#include "vt_kern.h"
50
 
51
#define SIZE(x) (sizeof(x)/sizeof((x)[0]))
52
 
53
#define KBD_REPORT_ERR
54
#define KBD_REPORT_UNKN
55
 
56
#ifndef KBD_DEFMODE
57
#define KBD_DEFMODE ((1 << VC_REPEAT) | (1 << VC_META))
58
#endif
59
 
60
/*
61
 * Starts with NumLock off.
62
 */
63
#ifndef KBD_DEFLEDS
64
#define KBD_DEFLEDS 0
65
#endif
66
 
67
#ifndef KBD_DEFLOCK
68
#define KBD_DEFLOCK 0
69
#endif
70
 
71
#define REPEAT_TIMEOUT HZ*300/1000
72
#define REPEAT_RATE    HZ*30/1000
73
 
74
extern void ctrl_alt_del (void);
75
extern void scrollback(int);
76
extern void scrollfront(int);
77
extern int kbd_drv_init(void);
78
extern void kbd_drv_setleds(unsigned int leds);
79
extern unsigned int keymap_count;
80
 
81
/*
82
 * these are the valid i/o ports we're allowed to change. they map all the
83
 * video ports
84
 */
85
#define GPFIRST 0x3b4
86
#define GPLAST 0x3df
87
#define GPNUM (GPLAST - GPFIRST + 1)
88
 
89
/*
90
 * global state includes the following, and various static variables
91
 * in this module: shift_state, diacr, npadch, dead_key_next.
92
 * (last_console is now a global variable)
93
 */
94
 
95
/* shift state counters.. */
96
static unsigned char k_down[NR_SHIFT] = {0, };
97
/* keyboard key bitmap */
98
#define BITS_PER_LONG (8*sizeof (unsigned long))
99
static unsigned long key_down[256/BITS_PER_LONG] = {0, };
100
static int dead_key_next;
101
 
102
/*
103
 * In order to retrieve the shift_state (for the mouse server), either
104
 * the variable must be global, or a new procedure must be created to
105
 * return the value. I chose the former way.
106
 */
107
/*static*/ int shift_state;
108
static int npadch            = -1;              /* -1 or number assembled on pad */
109
static unsigned char diacr;
110
static char rep;                                /* Flag telling character repeat */
111
static int kbd_repeatkey     = -1;
112
static int kbd_repeattimeout = REPEAT_TIMEOUT;
113
static int kbd_repeatrate    = REPEAT_RATE;
114
 
115
static struct kbd_struct * kbd;
116
static struct tty_struct * tty;
117
 
118
extern void compute_shiftstate (void);
119
 
120
typedef void (*k_hand)(unsigned char value, char up_flag);
121
typedef void (k_handfn)(unsigned char value, char up_flag);
122
 
123
static k_handfn
124
        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
125
        do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_ignore;
126
 
127
static k_hand key_handler[16] = {
128
        do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift,
129
        do_meta, do_ascii, do_lock, do_lowercase, do_slock,
130
        do_ignore, do_ignore, do_ignore
131
};
132
 
133
typedef void (*void_fnp)(void);
134
typedef void (void_fn)(void);
135
 
136
static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
137
        num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
138
        SAK, decr_console, incr_console, spawn_console, show_stack, bare_num;
139
 
140
static void_fnp spec_fn_table[] = {
141
        do_null,        enter,          show_ptregs,    show_mem,
142
        show_state,     send_intr,      lastcons,       caps_toggle,
143
        num,            hold,           scroll_forw,    scroll_back,
144
        boot_it,        caps_on,        compose,        SAK,
145
        decr_console,   incr_console,   show_stack,     bare_num
146
};
147
 
148
/* maximum values each key_handler can handle */
149
const int max_vals[] = {
150
        255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
151
        NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
152
        255, NR_ASCII - 1, NR_LOCK - 1, 255,
153
        NR_LOCK - 1
154
};
155
 
156
const int NR_TYPES = SIZE(max_vals);
157
 
158
static void put_queue(int);
159
static unsigned char handle_diacr(unsigned char);
160
 
161
/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
162
static struct pt_regs * pt_regs;
163
 
164
/*
165
 * Many other routines do put_queue, but I think either
166
 * they produce ASCII, or they produce some user-assigned
167
 * string, and in both cases we might assume that it is
168
 * in utf-8 already.
169
 */
170
void to_utf8(ushort c)
171
{
172
        if (c < 0x80)
173
                put_queue(c);                   /*  0*******  */
174
        else if (c < 0x800) {
175
                put_queue(0xc0 | (c >> 6));     /*  110***** 10******  */
176
                put_queue(0x80 | (c & 0x3f));
177
        } else {
178
                put_queue(0xe0 | (c >> 12));    /*  1110**** 10****** 10******  */
179
                put_queue(0x80 | ((c >> 6) & 0x3f));
180
                put_queue(0x80 | (c & 0x3f));
181
        }
182
        /* UTF-8 is defined for words of up to 31 bits,
183
           but we need only 16 bits here */
184
}
185
 
186
/*
187
 * As yet, we don't support setting and getting the
188
 * key codes.  I'll have to find out where this is used.
189
 */
190
int setkeycode(unsigned int scancode, unsigned int keycode)
191
{
192
        return -EINVAL;
193
}
194
 
195
int getkeycode(unsigned int scancode)
196
{
197
        return -EINVAL;
198
}
199
 
200
static void key_callback(unsigned long nr)
201
{
202
        rep = 1;
203
        mark_bh (KEYBOARD_BH);
204
}
205
 
206
static struct timer_list key_timer =
207
{
208
        NULL, NULL, 0, 0, key_callback
209
};
210
 
211
void kbd_reset(void)
212
{
213
        int i;
214
 
215
        for (i = 0; i < NR_SHIFT; i++)
216
                k_down[i] = 0;
217
        for (i = 0; i < 256/BITS_PER_LONG; i++)
218
                key_down[i] = 0;
219
        shift_state = 0;
220
}
221
 
222
void kbd_setregs(struct pt_regs *regs)
223
{
224
        pt_regs = regs;
225
}
226
 
227
static void kbd_processkey(unsigned int keycode, unsigned int up_flag, unsigned int autorepeat)
228
{
229
        del_timer(&key_timer);
230
        show_console();
231
        add_keyboard_randomness (keycode|(up_flag?0x100:0));
232
 
233
        tty = *vtdata.fgconsole->tty;
234
        kbd = vtdata.fgconsole->kbd;
235
 
236
        if (up_flag) {
237
                rep = 0;
238
                clear_bit (keycode, key_down);
239
                /* don't report an error if key is already up - happens when a ghost key is released */
240
        } else
241
                rep = set_bit (keycode, key_down);
242
 
243
        if (rep && !autorepeat)
244
                return;
245
 
246
        if (kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) {
247
                put_queue(keycode + (up_flag ? 0x80 : 0));
248
                return;
249
        }
250
 
251
        /*
252
         * We have to do our own auto-repeat processing...
253
         */
254
        if (!up_flag) {
255
                kbd_repeatkey = keycode;
256
                if (vc_kbd_mode(kbd, VC_REPEAT)) {
257
                        if (rep)
258
                                key_timer.expires = jiffies + kbd_repeatrate;
259
                        else
260
                                key_timer.expires = jiffies + kbd_repeattimeout;
261
                        add_timer(&key_timer);
262
                }
263
        } else
264
                kbd_repeatkey = -1;
265
 
266
        /*
267
         * Repeat a key only if the input buffers are empty or the
268
         * characters get echoed locally.  This makes key repeat usable
269
         * with slow applications and under heavy loads.
270
         */
271
        if (!rep ||
272
            (vc_kbd_mode (kbd, VC_REPEAT) && tty &&
273
             (L_ECHO(tty) || (tty->driver.chars_in_buffer (tty) == 0)))) {
274
                u_short keysym;
275
                u_char  type;
276
 
277
                /* the XOR below used to be an OR */
278
                int     shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
279
                u_short *key_map = key_maps[shift_final];
280
 
281
                if (key_map != NULL) {
282
                        keysym = key_map[keycode];
283
                        type   = KTYP(keysym);
284
 
285
                        if (type >= 0xf0) {
286
                                type -= 0xf0;
287
                                if (type == KT_LETTER) {
288
                                        type = KT_LATIN;
289
                                        if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
290
                                                key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
291
                                                if (key_map)
292
                                                        keysym = key_map[keycode];
293
                                        }
294
                                }
295
                                (*key_handler[type])(keysym & 0xff, up_flag);
296
                                if (type != KT_SLOCK)
297
                                        kbd->slockstate = 0;
298
                        } else {
299
                                /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */
300
                                if (!up_flag)
301
                                        to_utf8(keysym);
302
                        }
303
                } else {
304
                        /*
305
                         * maybe beep?
306
                         * we have at least to update shift_state
307
                         * how? two almost equivalent choices follow
308
                         */
309
#if 1
310
                        compute_shiftstate ();
311
#else
312
                        keysym = U(plain_map[keycode]);
313
                        type   = KTYP(keysym);
314
                        if (type == KT_SHIFT)
315
                                (*key_handler[type]) (keysym & 0xff, up_flag);
316
#endif
317
                }
318
        }
319
}
320
 
321
void kbd_keyboardkey(unsigned int keycode, unsigned int up_flag)
322
{
323
        kbd_processkey(keycode, up_flag, 0);
324
}
325
 
326
static void put_queue (int ch)
327
{
328
        wake_up (&keypress_wait);
329
        if (tty) {
330
                tty_insert_flip_char (tty, ch, 0);
331
                tty_schedule_flip (tty);
332
        }
333
}
334
 
335
static void puts_queue(char *cp)
336
{
337
        wake_up (&keypress_wait);
338
        if (!tty)
339
                return;
340
 
341
        while (*cp) {
342
                tty_insert_flip_char (tty, *cp, 0);
343
                cp++;
344
        }
345
        tty_schedule_flip (tty);
346
}
347
 
348
static void show_stack (void)
349
{
350
        unsigned long *p;
351
        unsigned long *q = (unsigned long *)((int)current->kernel_stack_page + 4096);
352
        int i;
353
        __asm__("mov %0, sp\n\t": "=r" (p));
354
 
355
        for (i = 0; p < q; p++, i++) {
356
                if(i && !(i & 7))
357
                        printk("\n");
358
                printk("%08lX ", *p);
359
        }
360
}
361
 
362
static void applkey(int key, char mode)
363
{
364
        static char buf[] = { 0x1b, 'O', 0x00, 0x00};
365
 
366
        buf[1] = (mode ? 'O' : '[');
367
        buf[2] = key;
368
        puts_queue(buf);
369
}
370
 
371
static void enter(void)
372
{
373
        put_queue (13);
374
        if (vc_kbd_mode(kbd, VC_CRLF))
375
                put_queue (10);
376
}
377
 
378
static void caps_toggle(void)
379
{
380
        if(rep)
381
                return;
382
        chg_vc_kbd_led(kbd, VC_CAPSLOCK);
383
}
384
 
385
static void caps_on (void)
386
{
387
        if (rep)
388
                return;
389
        set_vc_kbd_led (kbd, VC_CAPSLOCK);
390
}
391
 
392
static void show_ptregs (void)
393
{
394
        if (pt_regs)
395
                show_regs (pt_regs);
396
}
397
 
398
static void hold (void)
399
{
400
        if(rep || !tty)
401
                return;
402
 
403
        /*
404
         * Note: SCROLLOCK will be set (cleared) by stop_tty (start_tty);
405
         * these routines are also activated by ^S/^Q.
406
         * (And SCROLLOCK can also be set by the ioctl KDSKBLED.)
407
         */
408
        if (tty->stopped)
409
                start_tty (tty);
410
        else
411
                stop_tty (tty);
412
}
413
 
414
static void num (void)
415
{
416
        if(vc_kbd_mode(kbd,VC_APPLIC))
417
                applkey('P', 1);
418
        else
419
                bare_num ();
420
}
421
 
422
/*
423
 * Bind this to Shift-NumLock if you work in application keypad mode
424
 * but want to be able to change the NumLock flag.
425
 * Bind this to NumLock if you prefer that the NumLock key always
426
 * changes the NumLock flag.
427
 */
428
static void bare_num (void)
429
{
430
        if (!rep)
431
                chg_vc_kbd_led (kbd, VC_NUMLOCK);
432
}
433
 
434
static void lastcons (void)
435
{
436
        /* switch to the last used console, ChN */
437
        set_console(last_console);
438
}
439
 
440
static void decr_console (void)
441
{
442
        int i;
443
        int fgnum = vtdata.fgconsole->num - 1;
444
 
445
        for (i = fgnum - 1; i != fgnum; i--) {
446
                if (i == -1)
447
                        i = MAX_NR_CONSOLES - 1;
448
                if (vt_allocated (vt_con_data + i))
449
                        break;
450
        }
451
        set_console(vt_con_data + i);
452
}
453
 
454
static void incr_console (void)
455
{
456
        int i;
457
        int fgnum = vtdata.fgconsole->num - 1;
458
 
459
        for (i = fgnum + 1; i != fgnum; i++) {
460
                if (i == MAX_NR_CONSOLES)
461
                        i = 0;
462
                if (vt_allocated (vt_con_data + i))
463
                        break;
464
        }
465
        set_console(vt_con_data + i);
466
}
467
 
468
static void send_intr (void)
469
{
470
        if (!tty)
471
                return;
472
        tty_insert_flip_char (tty, 0, TTY_BREAK);
473
        tty_schedule_flip (tty);
474
}
475
 
476
static void scroll_forw (void)
477
{
478
        scrollfront(0);
479
}
480
 
481
static void scroll_back (void)
482
{
483
        scrollback(0);
484
}
485
 
486
static void boot_it (void)
487
{
488
        ctrl_alt_del();
489
}
490
 
491
static void compose (void)
492
{
493
        dead_key_next = 1;
494
}
495
 
496
int spawnpid, spawnsig;
497
 
498
static void spawn_console (void)
499
{
500
        if (spawnpid)
501
                if (kill_proc (spawnpid, spawnsig, 1))
502
                        spawnpid = 0;
503
}
504
 
505
static void SAK (void)
506
{
507
        do_SAK(tty);
508
#if 0
509
        /*
510
         * Need to fix SAK handling to fix up RAW/MEDIUM_RAW and
511
         * vt_cons modes before we can enable RAW/MEDIUM_RAW SAK
512
         * handling.
513
         *
514
         * We should do this some day --- the whole point of a secure
515
         * attention key is that it should be guaranteed to always
516
         * work.
517
         */
518
        vt_reset (vtdata.fgconsole);
519
        do_unblank_screen ();   /* not in interrupt routine? */
520
#endif
521
}
522
 
523
static void do_ignore (unsigned char value, char up_flag)
524
{
525
}
526
 
527
static void do_null (void)
528
{
529
        compute_shiftstate ();
530
}
531
 
532
static void do_spec (unsigned char value,char up_flag)
533
{
534
        if (up_flag)
535
                return;
536
        if (value >= SIZE(spec_fn_table))
537
                return;
538
        spec_fn_table[value] ();
539
}
540
 
541
static void do_lowercase (unsigned char value, char up_flag)
542
{
543
        printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n");
544
}
545
 
546
static void do_self(unsigned char value, char up_flag)
547
{
548
        if (up_flag)
549
                return;         /* no action, if this is a key release */
550
 
551
        if (diacr)
552
                value = handle_diacr (value);
553
 
554
        if (dead_key_next) {
555
                dead_key_next = 0;
556
                diacr = value;
557
                return;
558
        }
559
 
560
        put_queue (value);
561
}
562
 
563
#define A_GRAVE '`'
564
#define A_ACUTE '\''
565
#define A_CFLEX '^'
566
#define A_TILDE '~'
567
#define A_DIAER '"'
568
#define A_CEDIL ','
569
static unsigned char ret_diacr[] =
570
        {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL };
571
 
572
/* If a dead key pressed twice, output a character corresponding to it, */
573
/* otherwise just remember the dead key.                                */
574
 
575
static void do_dead(unsigned char value, char up_flag)
576
{
577
        if (up_flag)
578
                return;
579
 
580
        value = ret_diacr[value];
581
        if (diacr == value) { /* pressed twice */
582
                diacr = 0;
583
                put_queue (value);
584
                return;
585
        }
586
        diacr = value;
587
}
588
 
589
 
590
/* If space is pressed, return the character corresponding the pending  */
591
/* dead key, otherwise try to combine the two.                          */
592
 
593
static unsigned char handle_diacr(unsigned char ch)
594
{
595
        int d = diacr;
596
        int i;
597
 
598
        diacr = 0;
599
        if (ch == ' ')
600
                return d;
601
 
602
        for (i = 0; i < accent_table_size; i++) {
603
                if (accent_table[i].diacr == d && accent_table[i].base == ch)
604
                    return accent_table[i].result;
605
        }
606
 
607
        put_queue (d);
608
        return ch;
609
}
610
 
611
static void do_cons(unsigned char value, char up_flag)
612
{
613
        if (up_flag)
614
                return;
615
        set_console(vt_con_data + value);
616
}
617
 
618
static void do_fn(unsigned char value, char up_flag)
619
{
620
        if (up_flag)
621
                return;
622
        if (value < SIZE(func_table)) {
623
                if (func_table[value])
624
                        puts_queue (func_table[value]);
625
        } else
626
                printk (KERN_ERR "do_fn called with value=%d\n",value);
627
}
628
 
629
static void do_pad(unsigned char value, char up_flag)
630
{
631
        static const char *pad_chars = "0123456789+-*/\015,.?#";
632
        static const char *app_map = "pqrstuvwxylmRQMnn?S";
633
 
634
        if (up_flag)
635
                return;         /* no action, if this is a key release */
636
 
637
        /* kludge... shift forces cursor/number keys */
638
        if (vc_kbd_mode (kbd, VC_APPLIC) && !k_down[KG_SHIFT]) {
639
                applkey (app_map[value], 1);
640
                return;
641
        }
642
 
643
        if (!vc_kbd_led (kbd,VC_NUMLOCK))
644
                switch (value) {
645
                        case KVAL(K_PCOMMA):
646
                        case KVAL(K_PDOT):
647
                                do_fn (KVAL(K_REMOVE), 0);
648
                                return;
649
                        case KVAL(K_P0):
650
                                do_fn (KVAL(K_INSERT), 0);
651
                                return;
652
                        case KVAL(K_P1):
653
                                do_fn (KVAL(K_SELECT), 0);
654
                                return;
655
                        case KVAL(K_P2):
656
                                do_cur(KVAL(K_DOWN), 0);
657
                                return;
658
                        case KVAL(K_P3):
659
                                do_fn (KVAL(K_PGDN), 0);
660
                                return;
661
                        case KVAL(K_P4):
662
                                do_cur(KVAL(K_LEFT), 0);
663
                                return;
664
                        case KVAL(K_P6):
665
                                do_cur(KVAL(K_RIGHT), 0);
666
                                return;
667
                        case KVAL(K_P7):
668
                                do_fn (KVAL(K_FIND), 0);
669
                                return;
670
                        case KVAL(K_P8):
671
                                do_cur(KVAL(K_UP), 0);
672
                                return;
673
                        case KVAL(K_P9):
674
                                do_fn (KVAL(K_PGUP), 0);
675
                                return;
676
                        case KVAL(K_P5):
677
                                applkey('G',vc_kbd_mode(kbd, VC_APPLIC));
678
                                return;
679
        }
680
 
681
        put_queue (pad_chars[value]);
682
        if (value == KVAL(K_PENTER) && vc_kbd_mode (kbd, VC_CRLF))
683
                put_queue (10);
684
}
685
 
686
static void do_cur(unsigned char value, char up_flag)
687
{
688
        static const char *cur_chars = "BDCA";
689
        if (up_flag)
690
                return;
691
 
692
        applkey (cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE));
693
}
694
 
695
static void do_shift(unsigned char value, char up_flag)
696
{
697
    int old_state = shift_state;
698
 
699
    if (rep)
700
        return;
701
 
702
    /* Mimic typewriter: a CapsShift key acts like Shift but undoes CapsLock */
703
    if (value == KVAL(K_CAPSSHIFT)) {
704
        value = KVAL(K_SHIFT);
705
        if (!up_flag)
706
            clr_vc_kbd_led (kbd, VC_CAPSLOCK);
707
    }
708
 
709
    if(up_flag) {
710
        /* handle the case that two shift or control
711
           keys are depressed simultaneously */
712
        if(k_down[value])
713
            k_down[value]--;
714
    } else
715
        k_down[value]++;
716
 
717
    if(k_down[value])
718
        shift_state |= (1 << value);
719
    else
720
        shift_state &= ~ (1 << value);
721
 
722
    /* kludge */
723
    if(up_flag && shift_state != old_state && npadch != -1) {
724
        if(kbd->kbdmode == VC_UNICODE)
725
            to_utf8(npadch & 0xffff);
726
        else
727
            put_queue(npadch & 0xff);
728
        npadch = -1;
729
    }
730
}
731
 
732
/*
733
 * Called after returning from RAW mode or when changing consoles -
734
 * recompute k_down[] and shift_state from key_down[]
735
 * Maybe called when keymap is undefined so that shift key release is seen
736
 */
737
void compute_shiftstate(void)
738
{
739
        int i, j, k, sym, val;
740
 
741
        shift_state = 0;
742
        for (i = 0; i < SIZE(k_down); i++)
743
                k_down[i] = 0;
744
 
745
        for (i = 0; i < SIZE(key_down); i++)
746
                if (key_down[i]) {      /* skip this word if not a single bit on */
747
                        k = i * BITS_PER_LONG;
748
                        for (j = 0; j < BITS_PER_LONG; j++, k++)
749
                                if (test_bit (k, key_down)) {
750
                                        sym = U(plain_map[k]);
751
                                        if (KTYP(sym) == KT_SHIFT) {
752
                                                val = KVAL (sym);
753
                                                if (val == KVAL(K_CAPSSHIFT))
754
                                                        val = KVAL(K_SHIFT);
755
                                                k_down[val] ++;
756
                                                shift_state |= (1 << val);
757
                                        }
758
                                }
759
                }
760
}
761
 
762
static void do_meta(unsigned char value, char up_flag)
763
{
764
        if(up_flag)
765
                return;
766
 
767
        if(vc_kbd_mode(kbd, VC_META)) {
768
                put_queue ('\033');
769
                put_queue (value);
770
        } else
771
                put_queue (value | 0x80);
772
}
773
 
774
static void do_ascii(unsigned char value, char up_flag)
775
{
776
        int base;
777
 
778
        if (up_flag)
779
                return;
780
 
781
        if (value < 10) /* decimal input of code, while Alt depressed */
782
                base = 10;
783
        else {          /* hexadecimal input of code, while AltGr depressed */
784
                value -= 10;
785
                base = 16;
786
        }
787
 
788
        if(npadch == -1)
789
                npadch = value;
790
        else
791
                npadch = npadch * base + value;
792
}
793
 
794
static void do_lock (unsigned char value, char up_flag)
795
{
796
    if (up_flag || rep)
797
        return;
798
    chg_vc_kbd_lock (kbd, value);
799
}
800
 
801
static void do_slock (unsigned char value, char up_flag)
802
{
803
    if (up_flag || rep)
804
        return;
805
    chg_vc_kbd_slock (kbd, value);
806
}
807
 
808
/*
809
 * The leds display either
810
 * (i)   The status of NumLock, CapsLock and ScrollLock.
811
 * (ii)  Whatever pattern of lights people wait to show using KDSETLED.
812
 * (iii) Specified bits of specified words in kernel memory.
813
 */
814
 
815
static unsigned char ledstate = 0xff; /* undefined */
816
static unsigned char ledioctl;
817
 
818
unsigned char getledstate(void)
819
{
820
    return ledstate;
821
}
822
 
823
void setledstate(struct kbd_struct *kbd, unsigned int led)
824
{
825
    if(!(led & ~7)) {
826
        ledioctl = led;
827
        kbd->ledmode = LED_SHOW_IOCTL;
828
    } else
829
        kbd->ledmode = LED_SHOW_FLAGS;
830
    set_leds();
831
}
832
 
833
static struct ledptr {
834
    unsigned int *addr;
835
    unsigned int mask;
836
    unsigned char valid:1;
837
} ledptrs[3];
838
 
839
void register_leds(int console, unsigned int led,
840
                  unsigned int *addr, unsigned int mask)
841
{
842
    struct kbd_struct *kbd = vt_con_data[console].kbd;
843
    if(led < 3) {
844
        ledptrs[led].addr = addr;
845
        ledptrs[led].mask = mask;
846
        ledptrs[led].valid= 1;
847
        kbd->ledmode = LED_SHOW_MEM;
848
    } else
849
        kbd->ledmode = LED_SHOW_FLAGS;
850
}
851
 
852
static inline unsigned char getleds(void)
853
{
854
    struct kbd_struct *kbd = vtdata.fgconsole->kbd;
855
    unsigned char leds;
856
 
857
    if(kbd->ledmode == LED_SHOW_IOCTL)
858
        return ledioctl;
859
    leds = kbd->ledflagstate;
860
    if (kbd->ledmode == LED_SHOW_MEM) {
861
        if (ledptrs[0].valid) {
862
            if (*ledptrs[0].addr & ledptrs[0].mask)
863
                leds |= 1;
864
            else
865
                leds &= ~1;
866
        }
867
        if (ledptrs[1].valid) {
868
            if (*ledptrs[1].addr & ledptrs[1].mask)
869
                leds |= 2;
870
            else
871
                leds &= ~2;
872
        }
873
        if (ledptrs[2].valid) {
874
            if(*ledptrs[2].addr & ledptrs[2].mask)
875
                leds |= 4;
876
            else
877
                leds &= ~4;
878
        }
879
    }
880
    return leds;
881
}
882
 
883
/*
884
 * This routine is the bottom half of the keyboard interrupt
885
 * routine, and runs with all interrupts enabled.  It does
886
 * console changing, led setting and copy_to_cooked, which can
887
 * take a reasonably long time.
888
 *
889
 * Aside from timing (which isn't really that important for
890
 * keyboard interrupts as they happen often), using the software
891
 * interrupt routines for this thing allows us to easily mask
892
 * this when we don't want any of the above to happen.  Not yet
893
 * used, but this allows for easy and efficient race-condition
894
 * prevention later on.
895
 */
896
static void kbd_bh(void)
897
{
898
        unsigned char leds = getleds();
899
 
900
        tty = *vtdata.fgconsole->tty;
901
        kbd = vtdata.fgconsole->kbd;
902
 
903
        if (rep) {
904
                /*
905
                 * This prevents the kbd_key routine from being called
906
                 * twice, once by this BH, and once by the interrupt
907
                 * routine.  Maybe we should put the key press in a
908
                 * buffer or variable, and then call the BH...
909
                 */
910
                disable_irq (IRQ_KEYBOARDRX);
911
                if (kbd_repeatkey != -1)
912
                        kbd_processkey (kbd_repeatkey, 0, 1);
913
                enable_irq (IRQ_KEYBOARDRX);
914
                rep = 0;
915
        }
916
 
917
        if (leds != ledstate) {
918
                ledstate = leds;
919
                kbd_drv_setleds(leds);
920
        }
921
}
922
 
923
/*
924
 * Initialise a kbd struct
925
 */
926
int kbd_struct_init (struct vt *vt, int init)
927
{
928
        vt->kbd->ledflagstate = vt->kbd->default_ledflagstate = KBD_DEFLEDS;
929
        vt->kbd->ledmode = LED_SHOW_FLAGS;
930
        vt->kbd->lockstate = KBD_DEFLOCK;
931
        vt->kbd->slockstate = 0;
932
        vt->kbd->modeflags = KBD_DEFMODE;
933
        vt->kbd->kbdmode = VC_XLATE;
934
        return 0;
935
}
936
 
937
int kbd_ioctl (struct vt *vt, int cmd, unsigned long arg)
938
{
939
    asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
940
    int i;
941
 
942
    switch (cmd) {
943
    case KDGKBTYPE:
944
        /*
945
         * This is naive.
946
         */
947
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (unsigned char));
948
        if (!i)
949
            put_user (KB_101, (char *)arg);
950
        return i;
951
 
952
    case KDADDIO:
953
    case KDDELIO:
954
        /*
955
         * KDADDIO and KDDELIO may be able to add ports beyond what
956
         * we reject here, but to be safe...
957
         */
958
        if (arg < GPFIRST || arg > GPLAST)
959
            return -EINVAL;
960
        return sys_ioperm (arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
961
 
962
    case KDENABIO:
963
    case KDDISABIO:
964
        return sys_ioperm (GPFIRST, GPLAST, (cmd == KDENABIO)) ? -ENXIO : 0;
965
 
966
    case KDMAPDISP:
967
    case KDUNMAPDISP:
968
        /*
969
         * These work like a combination of mmap and KDENABIO.
970
         * this could easily be finished.
971
         */
972
        return -EINVAL;
973
 
974
    case KDSKBMODE:
975
        switch (arg) {
976
        case K_RAW:
977
            vt->kbd->kbdmode = VC_RAW;
978
            break;
979
        case K_MEDIUMRAW:
980
            vt->kbd->kbdmode = VC_MEDIUMRAW;
981
            break;
982
        case K_XLATE:
983
            vt->kbd->kbdmode = VC_XLATE;
984
            compute_shiftstate ();
985
            break;
986
        case K_UNICODE:
987
            vt->kbd->kbdmode = VC_UNICODE;
988
            compute_shiftstate ();
989
            break;
990
        default:
991
            return -EINVAL;
992
        }
993
        if (tty->ldisc.flush_buffer)
994
            tty->ldisc.flush_buffer (*vt->tty);
995
        return 0;
996
 
997
    case KDGKBMODE:
998
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (unsigned long));
999
        if (!i) {
1000
            int ucval;
1001
            ucval = ((vt->kbd->kbdmode == VC_RAW) ? K_RAW :
1002
                     (vt->kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
1003
                     (vt->kbd->kbdmode == VC_UNICODE) ? K_UNICODE : K_XLATE);
1004
            put_user (ucval, (int *)arg);
1005
        }
1006
        return i;
1007
 
1008
    case KDSKBMETA:
1009
        /*
1010
         * this could be folded into KDSKBMODE, but for compatibility
1011
         * reasons, it is not so easy to fold kDGKBMETA into KDGKBMODE.
1012
         */
1013
        switch (arg) {
1014
        case K_METABIT:
1015
            clr_vc_kbd_mode (vt->kbd, VC_META);
1016
            break;
1017
        case K_ESCPREFIX:
1018
            set_vc_kbd_mode (vt->kbd, VC_META);
1019
            break;
1020
        default:
1021
            return -EINVAL;
1022
        }
1023
        return 0;
1024
 
1025
    case KDGKBMETA:
1026
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (unsigned long));
1027
        if (!i) {
1028
            int ucval;
1029
            ucval = (vc_kbd_mode (vt->kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
1030
            put_user (ucval, (int *)arg);
1031
        }
1032
        return i;
1033
 
1034
    case KDGETKEYCODE: {
1035
        struct kbkeycode *const a = (struct kbkeycode *)arg;
1036
 
1037
        i = verify_area (VERIFY_WRITE, a, sizeof (struct kbkeycode));
1038
        if (!i) {
1039
            unsigned int sc;
1040
 
1041
            sc = get_user (&a->scancode);
1042
            i = getkeycode (sc);
1043
            if (i > 0)
1044
                put_user (i, &a->keycode);
1045
            i = 0;
1046
        }
1047
        return i;
1048
        }
1049
 
1050
    case KDSETKEYCODE: {
1051
        struct kbkeycode *const a = (struct kbkeycode *)arg;
1052
 
1053
        i = verify_area (VERIFY_READ, a, sizeof (struct kbkeycode));
1054
        if (!i) {
1055
            unsigned int sc, kc;
1056
            sc = get_user (&a->scancode);
1057
            kc = get_user (&a->keycode);
1058
            i = setkeycode (sc, kc);
1059
        }
1060
        return i;
1061
        }
1062
 
1063
    case KDGKBENT: {
1064
        struct kbentry *const a = (struct kbentry *)arg;
1065
 
1066
        i = verify_area (VERIFY_WRITE, a, sizeof (struct kbentry));
1067
        if (!i) {
1068
            ushort *keymap, val;
1069
            u_char s;
1070
            i = get_user (&a->kb_index);
1071
            if (i >= NR_KEYS)
1072
                return -EINVAL;
1073
            s = get_user (&a->kb_table);
1074
            if (s >= MAX_NR_KEYMAPS)
1075
                return -EINVAL;
1076
            keymap = key_maps[s];
1077
            if (keymap) {
1078
                val = U(keymap[i]);
1079
                if (vt->kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
1080
                    val = K_HOLE;
1081
            } else
1082
                val = (i ? K_HOLE : K_NOSUCHMAP);
1083
            put_user (val, &a->kb_value);
1084
            i = 0;
1085
        }
1086
        return i;
1087
        }
1088
 
1089
    case KDSKBENT: {
1090
        struct kbentry *const a = (struct kbentry *)arg;
1091
 
1092
        i = verify_area (VERIFY_WRITE, a, sizeof (struct kbentry));
1093
        if (!i) {
1094
            ushort *key_map;
1095
            u_char s;
1096
            u_short v, ov;
1097
 
1098
            if ((i = get_user(&a->kb_index)) >= NR_KEYS)
1099
                return -EINVAL;
1100
            if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
1101
                return -EINVAL;
1102
            v = get_user(&a->kb_value);
1103
            if (!i && v == K_NOSUCHMAP) {
1104
                /* disallocate map */
1105
                key_map = key_maps[s];
1106
                if (s && key_map) {
1107
                    key_maps[s] = 0;
1108
                    if (key_map[0] == U(K_ALLOCATED)) {
1109
                        kfree_s(key_map, sizeof(plain_map));
1110
                        keymap_count--;
1111
                    }
1112
                }
1113
                return 0;
1114
            }
1115
 
1116
            if (KTYP(v) < NR_TYPES) {
1117
                if (KVAL(v) > max_vals[KTYP(v)])
1118
                    return -EINVAL;
1119
            } else
1120
                if (kbd->kbdmode != VC_UNICODE)
1121
                    return -EINVAL;
1122
 
1123
            /* assignment to entry 0 only tests validity of args */
1124
            if (!i)
1125
                return 0;
1126
 
1127
            if (!(key_map = key_maps[s])) {
1128
                int j;
1129
 
1130
                if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
1131
                    return -EPERM;
1132
 
1133
                key_map = (ushort *) kmalloc(sizeof(plain_map),
1134
                                             GFP_KERNEL);
1135
                if (!key_map)
1136
                    return -ENOMEM;
1137
                key_maps[s] = key_map;
1138
                key_map[0] = U(K_ALLOCATED);
1139
                for (j = 1; j < NR_KEYS; j++)
1140
                    key_map[j] = U(K_HOLE);
1141
                keymap_count++;
1142
            }
1143
            ov = U(key_map[i]);
1144
            if (v == ov)
1145
                return 0;        /* nothing to do */
1146
            /*
1147
             * Only the Superuser can set or unset the Secure
1148
             * Attention Key.
1149
             */
1150
            if (((ov == K_SAK) || (v == K_SAK)) && !suser())
1151
                return -EPERM;
1152
            key_map[i] = U(v);
1153
            if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
1154
                compute_shiftstate();
1155
            return 0;
1156
        }
1157
        return i;
1158
        }
1159
 
1160
    case KDGKBSENT: {
1161
        struct kbsentry *a = (struct kbsentry *)arg;
1162
        char *p;
1163
        u_char *q;
1164
        int sz;
1165
 
1166
        i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
1167
        if (i)
1168
            return i;
1169
        if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
1170
            return -EINVAL;
1171
        sz = sizeof(a->kb_string) - 1; /* sz should have been
1172
                                          a struct member */
1173
        q = a->kb_string;
1174
        p = func_table[i];
1175
        if(p)
1176
            for ( ; *p && sz; p++, sz--)
1177
                put_user(*p, q++);
1178
        put_user('\0', q);
1179
        return ((p && *p) ? -EOVERFLOW : 0);
1180
        }
1181
 
1182
    case KDSKBSENT: {
1183
        struct kbsentry * const a = (struct kbsentry *)arg;
1184
        int delta;
1185
        char *first_free, *fj, *fnw;
1186
        int j, k, sz;
1187
        u_char *p;
1188
        char *q;
1189
 
1190
        i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
1191
        if (i)
1192
            return i;
1193
        if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
1194
            return -EINVAL;
1195
        q = func_table[i];
1196
 
1197
        first_free = funcbufptr + (funcbufsize - funcbufleft);
1198
        for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
1199
        if (j < MAX_NR_FUNC)
1200
            fj = func_table[j];
1201
        else
1202
            fj = first_free;
1203
 
1204
        delta = (q ? -strlen(q) : 1);
1205
        sz = sizeof(a->kb_string);      /* sz should have been
1206
                                           a struct member */
1207
        for (p = a->kb_string; get_user(p) && sz; p++,sz--)
1208
            delta++;
1209
        if (!sz)
1210
            return -EOVERFLOW;
1211
        if (delta <= funcbufleft) {     /* it fits in current buf */
1212
            if (j < MAX_NR_FUNC) {
1213
                memmove(fj + delta, fj, first_free - fj);
1214
                for (k = j; k < MAX_NR_FUNC; k++)
1215
                    if (func_table[k])
1216
                        func_table[k] += delta;
1217
            }
1218
            if (!q)
1219
                func_table[i] = fj;
1220
            funcbufleft -= delta;
1221
        } else {                        /* allocate a larger buffer */
1222
            sz = 256;
1223
            while (sz < funcbufsize - funcbufleft + delta)
1224
                sz <<= 1;
1225
            fnw = (char *) kmalloc(sz, GFP_KERNEL);
1226
            if(!fnw)
1227
                return -ENOMEM;
1228
 
1229
            if (!q)
1230
                func_table[i] = fj;
1231
            if (fj > funcbufptr)
1232
                memmove(fnw, funcbufptr, fj - funcbufptr);
1233
            for (k = 0; k < j; k++)
1234
                if (func_table[k])
1235
                    func_table[k] = fnw + (func_table[k] - funcbufptr);
1236
 
1237
            if (first_free > fj) {
1238
                memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
1239
                for (k = j; k < MAX_NR_FUNC; k++)
1240
                    if (func_table[k])
1241
                        func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
1242
            }
1243
            if (funcbufptr != func_buf)
1244
                kfree_s(funcbufptr, funcbufsize);
1245
            funcbufptr = fnw;
1246
            funcbufleft = funcbufleft - delta + sz - funcbufsize;
1247
            funcbufsize = sz;
1248
        }
1249
        for (p = a->kb_string, q = func_table[i]; ; p++, q++)
1250
            if (!(*q = get_user(p)))
1251
                break;
1252
        return 0;
1253
        }
1254
 
1255
    case KDGKBDIACR: {
1256
        struct kbdiacrs *a = (struct kbdiacrs *)arg;
1257
 
1258
        i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
1259
        if (i)
1260
            return i;
1261
        put_user(accent_table_size, &a->kb_cnt);
1262
        memcpy_tofs(a->kbdiacr, accent_table,
1263
                    accent_table_size*sizeof(struct kbdiacr));
1264
        return 0;
1265
        }
1266
 
1267
    case KDSKBDIACR: {
1268
        struct kbdiacrs *a = (struct kbdiacrs *)arg;
1269
        unsigned int ct;
1270
 
1271
        i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
1272
        if (i)
1273
            return i;
1274
        ct = get_user(&a->kb_cnt);
1275
        if (ct >= MAX_DIACR)
1276
            return -EINVAL;
1277
        accent_table_size = ct;
1278
        memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
1279
        return 0;
1280
        }
1281
 
1282
    /* the ioctls below read/set the flags usually shown in the leds */
1283
    /* don't use them - they will go away without warning */
1284
    case KDGKBLED:
1285
        i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
1286
        if (i)
1287
            return i;
1288
        put_user(vt->kbd->ledflagstate |
1289
                    (vt->kbd->default_ledflagstate << 4), (char *) arg);
1290
        return 0;
1291
 
1292
    case KDSKBLED:
1293
        if (arg & ~0x77)
1294
            return -EINVAL;
1295
        vt->kbd->ledflagstate = (arg & 7);
1296
        vt->kbd->default_ledflagstate = ((arg >> 4) & 7);
1297
        set_leds ();
1298
        return 0;
1299
 
1300
    /* the ioctls below only set the lights, not the functions */
1301
    /* for those, see KDGKBLED and KDSKBLED above */
1302
    case KDGETLED:
1303
        i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
1304
        if (i)
1305
                return i;
1306
        put_user(getledstate(), (char *) arg);
1307
        return 0;
1308
 
1309
    case KDSETLED:
1310
        setledstate(kbd, arg);
1311
        return 0;
1312
 
1313
    /*
1314
     * A process can indicate its willingness to accept signals
1315
     * generated by pressing an appropriate key combination.
1316
     * Thus, one can have a daemon that e.g. spawns a new console
1317
     * upon a keypess and then changes to it.
1318
     * Probably init should be changed to do this (and have a
1319
     * field ks (`keyboard signal') in inittab describing the
1320
     * desired acion), so that the number of background daemons
1321
     * does not increase.
1322
     */
1323
    case KDSIGACCEPT: {
1324
        if (arg < 1 || arg > NSIG || arg == SIGKILL)
1325
            return -EINVAL;
1326
        spawnpid = current->pid;
1327
        spawnsig = arg;
1328
        return 0;
1329
        }
1330
    default:
1331
        return -ENOIOCTLCMD;
1332
    }
1333
}
1334
 
1335
int kbd_init (void)
1336
{
1337
        int ret;
1338
        init_bh(KEYBOARD_BH, kbd_bh);
1339
        ret = kbd_drv_init();
1340
        mark_bh(KEYBOARD_BH);
1341
        return ret;
1342
}

powered by: WebSVN 2.1.0

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