Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / drivers / kbd.c
1 /*
2  * <kbd.c>
3  *
4  * Open Hack'Ware BIOS generic keyboard input translation.
5  *
6  *  Copyright (c) 2005 Jocelyn Mayer
7  *
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License V2
10  *   as published by the Free Software Foundation
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
20  */
21
22 #include "config.h"
23 #include "libc/string.h"
24 #include "asm/types.h"
25 #include "kbd.h"
26
27 //#define DEBUG_KBD
28 #ifdef DEBUG_KBD
29 #define KBD_DPRINTF(fmt, args...) \
30 do { printk("KBD - %s: " fmt, __func__ , ##args); } while (0)
31 #else
32 #define KBD_DPRINTF(fmt, args...) do { } while (0)
33 #endif
34
35 int kbd_set_keymap (kbd_t *kbd, int nb_keys, const keymap_t *keymap, const char **sequences)
36 {
37     kbd->nb_keys = nb_keys;
38     kbd->keymap = keymap;
39     kbd->sequences = sequences;
40
41     return 0;
42 }
43
44 int kbd_translate_key (kbd_t *kbd, int keycode, int up_down, char *sequence)
45 {
46     const keymap_t *keyt;
47     int mod_state, key, type;
48     int ret;
49
50     ret = -1;
51     /* Get key table */
52     if (keycode < kbd->nb_keys) {
53         keyt = &kbd->keymap[keycode];
54         /* Get modifier state */
55         mod_state = (kbd->mod_state | (kbd->mod_state >> 8)) & 0xFF;
56         /* Adjust with lock */
57         if (keyt->lck_shift >= 0) {
58             if ((kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01) {
59                 KBD_DPRINTF("adjust with lock %02x => %02x (%d %08x)\n",
60                             mod_state,
61                             mod_state ^ ((kbd->mod_state >>
62                                           (16 + keyt->lck_shift)) &
63                                          0x01),
64                             keyt->lck_shift, kbd->mod_state);
65             }
66             mod_state ^= (kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01;
67         }
68         key = keyt->trans[mod_state];
69         type = key & 0xFF000000;
70         key &= ~0xFF000000;
71         switch (type) {
72         case KBD_TYPE_REGULAR:
73             if (!up_down) {
74                 /* We don't care about up events on "normal" keys */
75                 *sequence = key;
76                 ret = 1;
77             }
78             break;
79         case KBD_TYPE_SEQUENCE:
80             if (!up_down) {
81                 /* We don't care about up events on "normal" keys */
82                 ret = strlen(kbd->sequences[key]);
83                 memcpy(sequence, kbd->sequences[key], ret);
84             }
85             break;
86         case KBD_TYPE_LOCK:
87             if (!up_down) {
88                 kbd->mod_state ^= key;
89                 ret = -2;
90                 KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n",
91                             type, key, up_down ? "up" : "down",
92                             kbd->mod_state);
93             }
94             break;
95         case KBD_TYPE_LMOD:
96         case KBD_TYPE_RMOD:
97             if (up_down)
98                 kbd->mod_state &= ~key;
99             else
100                 kbd->mod_state |= key;
101             KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n",
102                         type, key, up_down ? "up" : "down", kbd->mod_state);
103             ret = -2; /* The caller may know the key was a modifier */
104             break;
105         default:
106             KBD_DPRINTF("Unknown key: keycode=%02x mod_state=%02x (%08x)\n",
107                         keycode, mod_state, kbd->mod_state);
108             break;
109         }
110     } else {
111         KBD_DPRINTF("Unmanaged key: keycode=%02x mod_state %08x\n",
112                     keycode, kbd->mod_state);
113     }
114
115     return ret;
116 }