Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/kernel/debug/kdb/kdb_keyboard.c
17237 views
1
/*
2
* Kernel Debugger Architecture Dependent Console I/O handler
3
*
4
* This file is subject to the terms and conditions of the GNU General Public
5
* License.
6
*
7
* Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved.
8
* Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
9
*/
10
11
#include <linux/kdb.h>
12
#include <linux/keyboard.h>
13
#include <linux/ctype.h>
14
#include <linux/module.h>
15
#include <linux/io.h>
16
17
/* Keyboard Controller Registers on normal PCs. */
18
19
#define KBD_STATUS_REG 0x64 /* Status register (R) */
20
#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
21
22
/* Status Register Bits */
23
24
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
25
#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
26
27
static int kbd_exists;
28
29
/*
30
* Check if the keyboard controller has a keypress for us.
31
* Some parts (Enter Release, LED change) are still blocking polled here,
32
* but hopefully they are all short.
33
*/
34
int kdb_get_kbd_char(void)
35
{
36
int scancode, scanstatus;
37
static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */
38
static int shift_key; /* Shift next keypress */
39
static int ctrl_key;
40
u_short keychar;
41
42
if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
43
(inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
44
kbd_exists = 0;
45
return -1;
46
}
47
kbd_exists = 1;
48
49
if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
50
return -1;
51
52
/*
53
* Fetch the scancode
54
*/
55
scancode = inb(KBD_DATA_REG);
56
scanstatus = inb(KBD_STATUS_REG);
57
58
/*
59
* Ignore mouse events.
60
*/
61
if (scanstatus & KBD_STAT_MOUSE_OBF)
62
return -1;
63
64
/*
65
* Ignore release, trigger on make
66
* (except for shift keys, where we want to
67
* keep the shift state so long as the key is
68
* held down).
69
*/
70
71
if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
72
/*
73
* Next key may use shift table
74
*/
75
if ((scancode & 0x80) == 0)
76
shift_key = 1;
77
else
78
shift_key = 0;
79
return -1;
80
}
81
82
if ((scancode&0x7f) == 0x1d) {
83
/*
84
* Left ctrl key
85
*/
86
if ((scancode & 0x80) == 0)
87
ctrl_key = 1;
88
else
89
ctrl_key = 0;
90
return -1;
91
}
92
93
if ((scancode & 0x80) != 0)
94
return -1;
95
96
scancode &= 0x7f;
97
98
/*
99
* Translate scancode
100
*/
101
102
if (scancode == 0x3a) {
103
/*
104
* Toggle caps lock
105
*/
106
shift_lock ^= 1;
107
108
#ifdef KDB_BLINK_LED
109
kdb_toggleled(0x4);
110
#endif
111
return -1;
112
}
113
114
if (scancode == 0x0e) {
115
/*
116
* Backspace
117
*/
118
return 8;
119
}
120
121
/* Special Key */
122
switch (scancode) {
123
case 0xF: /* Tab */
124
return 9;
125
case 0x53: /* Del */
126
return 4;
127
case 0x47: /* Home */
128
return 1;
129
case 0x4F: /* End */
130
return 5;
131
case 0x4B: /* Left */
132
return 2;
133
case 0x48: /* Up */
134
return 16;
135
case 0x50: /* Down */
136
return 14;
137
case 0x4D: /* Right */
138
return 6;
139
}
140
141
if (scancode == 0xe0)
142
return -1;
143
144
/*
145
* For Japanese 86/106 keyboards
146
* See comment in drivers/char/pc_keyb.c.
147
* - Masahiro Adegawa
148
*/
149
if (scancode == 0x73)
150
scancode = 0x59;
151
else if (scancode == 0x7d)
152
scancode = 0x7c;
153
154
if (!shift_lock && !shift_key && !ctrl_key) {
155
keychar = plain_map[scancode];
156
} else if ((shift_lock || shift_key) && key_maps[1]) {
157
keychar = key_maps[1][scancode];
158
} else if (ctrl_key && key_maps[4]) {
159
keychar = key_maps[4][scancode];
160
} else {
161
keychar = 0x0020;
162
kdb_printf("Unknown state/scancode (%d)\n", scancode);
163
}
164
keychar &= 0x0fff;
165
if (keychar == '\t')
166
keychar = ' ';
167
switch (KTYP(keychar)) {
168
case KT_LETTER:
169
case KT_LATIN:
170
if (isprint(keychar))
171
break; /* printable characters */
172
/* drop through */
173
case KT_SPEC:
174
if (keychar == K_ENTER)
175
break;
176
/* drop through */
177
default:
178
return -1; /* ignore unprintables */
179
}
180
181
if ((scancode & 0x7f) == 0x1c) {
182
/*
183
* enter key. All done. Absorb the release scancode.
184
*/
185
while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
186
;
187
188
/*
189
* Fetch the scancode
190
*/
191
scancode = inb(KBD_DATA_REG);
192
scanstatus = inb(KBD_STATUS_REG);
193
194
while (scanstatus & KBD_STAT_MOUSE_OBF) {
195
scancode = inb(KBD_DATA_REG);
196
scanstatus = inb(KBD_STATUS_REG);
197
}
198
199
if (scancode != 0x9c) {
200
/*
201
* Wasn't an enter-release, why not?
202
*/
203
kdb_printf("kdb: expected enter got 0x%x status 0x%x\n",
204
scancode, scanstatus);
205
}
206
207
return 13;
208
}
209
210
return keychar & 0xff;
211
}
212
EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
213
214