Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/kernel/debug/kdb/kdb_keyboard.c
29278 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/io.h>
15
16
#include "kdb_private.h"
17
18
/* Keyboard Controller Registers on normal PCs. */
19
20
#define KBD_STATUS_REG 0x64 /* Status register (R) */
21
#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
22
23
/* Status Register Bits */
24
25
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
26
#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
27
28
#define CTRL(c) ((c) - 64)
29
30
static int kbd_exists;
31
static int kbd_last_ret;
32
33
/*
34
* Check if the keyboard controller has a keypress for us.
35
* Some parts (Enter Release, LED change) are still blocking polled here,
36
* but hopefully they are all short.
37
*/
38
int kdb_get_kbd_char(void)
39
{
40
int scancode, scanstatus;
41
static int shift_lock; /* CAPS LOCK state (0-off, 1-on) */
42
static int shift_key; /* Shift next keypress */
43
static int ctrl_key;
44
u_short keychar;
45
46
if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
47
(inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
48
kbd_exists = 0;
49
return -1;
50
}
51
kbd_exists = 1;
52
53
if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
54
return -1;
55
56
/*
57
* Fetch the scancode
58
*/
59
scancode = inb(KBD_DATA_REG);
60
scanstatus = inb(KBD_STATUS_REG);
61
62
/*
63
* Ignore mouse events.
64
*/
65
if (scanstatus & KBD_STAT_MOUSE_OBF)
66
return -1;
67
68
/*
69
* Ignore release, trigger on make
70
* (except for shift keys, where we want to
71
* keep the shift state so long as the key is
72
* held down).
73
*/
74
75
if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
76
/*
77
* Next key may use shift table
78
*/
79
if ((scancode & 0x80) == 0)
80
shift_key = 1;
81
else
82
shift_key = 0;
83
return -1;
84
}
85
86
if ((scancode&0x7f) == 0x1d) {
87
/*
88
* Left ctrl key
89
*/
90
if ((scancode & 0x80) == 0)
91
ctrl_key = 1;
92
else
93
ctrl_key = 0;
94
return -1;
95
}
96
97
if ((scancode & 0x80) != 0) {
98
if (scancode == 0x9c)
99
kbd_last_ret = 0;
100
return -1;
101
}
102
103
scancode &= 0x7f;
104
105
/*
106
* Translate scancode
107
*/
108
109
if (scancode == 0x3a) {
110
/*
111
* Toggle caps lock
112
*/
113
shift_lock ^= 1;
114
115
#ifdef KDB_BLINK_LED
116
kdb_toggleled(0x4);
117
#endif
118
return -1;
119
}
120
121
if (scancode == 0x0e) {
122
/*
123
* Backspace
124
*/
125
return 8;
126
}
127
128
/* Translate special keys to equivalent CTRL control characters */
129
switch (scancode) {
130
case 0xF: /* Tab */
131
return CTRL('I');
132
case 0x53: /* Del */
133
return CTRL('D');
134
case 0x47: /* Home */
135
return CTRL('A');
136
case 0x4F: /* End */
137
return CTRL('E');
138
case 0x4B: /* Left */
139
return CTRL('B');
140
case 0x48: /* Up */
141
return CTRL('P');
142
case 0x50: /* Down */
143
return CTRL('N');
144
case 0x4D: /* Right */
145
return CTRL('F');
146
}
147
148
if (scancode == 0xe0)
149
return -1;
150
151
/*
152
* For Japanese 86/106 keyboards
153
* See comment in drivers/char/pc_keyb.c.
154
* - Masahiro Adegawa
155
*/
156
if (scancode == 0x73)
157
scancode = 0x59;
158
else if (scancode == 0x7d)
159
scancode = 0x7c;
160
161
if (!shift_lock && !shift_key && !ctrl_key) {
162
keychar = plain_map[scancode];
163
} else if ((shift_lock || shift_key) && key_maps[1]) {
164
keychar = key_maps[1][scancode];
165
} else if (ctrl_key && key_maps[4]) {
166
keychar = key_maps[4][scancode];
167
} else {
168
keychar = 0x0020;
169
kdb_printf("Unknown state/scancode (%d)\n", scancode);
170
}
171
keychar &= 0x0fff;
172
if (keychar == '\t')
173
keychar = ' ';
174
switch (KTYP(keychar)) {
175
case KT_LETTER:
176
case KT_LATIN:
177
switch (keychar) {
178
/* non-printable supported control characters */
179
case CTRL('A'): /* Home */
180
case CTRL('B'): /* Left */
181
case CTRL('D'): /* Del */
182
case CTRL('E'): /* End */
183
case CTRL('F'): /* Right */
184
case CTRL('I'): /* Tab */
185
case CTRL('N'): /* Down */
186
case CTRL('P'): /* Up */
187
return keychar;
188
}
189
190
if (isprint(keychar))
191
break; /* printable characters */
192
fallthrough;
193
case KT_SPEC:
194
if (keychar == K_ENTER)
195
break;
196
fallthrough;
197
default:
198
return -1; /* ignore unprintables */
199
}
200
201
if (scancode == 0x1c) {
202
kbd_last_ret = 1;
203
return 13;
204
}
205
206
return keychar & 0xff;
207
}
208
EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
209
210
/*
211
* Best effort cleanup of ENTER break codes on leaving KDB. Called on
212
* exiting KDB, when we know we processed an ENTER or KP ENTER scan
213
* code.
214
*/
215
void kdb_kbd_cleanup_state(void)
216
{
217
int scancode, scanstatus;
218
219
/*
220
* Nothing to clean up, since either
221
* ENTER was never pressed, or has already
222
* gotten cleaned up.
223
*/
224
if (!kbd_last_ret)
225
return;
226
227
kbd_last_ret = 0;
228
/*
229
* Enter key. Need to absorb the break code here, lest it gets
230
* leaked out if we exit KDB as the result of processing 'g'.
231
*
232
* This has several interesting implications:
233
* + Need to handle KP ENTER, which has break code 0xe0 0x9c.
234
* + Need to handle repeat ENTER and repeat KP ENTER. Repeats
235
* only get a break code at the end of the repeated
236
* sequence. This means we can't propagate the repeated key
237
* press, and must swallow it away.
238
* + Need to handle possible PS/2 mouse input.
239
* + Need to handle mashed keys.
240
*/
241
242
while (1) {
243
while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
244
cpu_relax();
245
246
/*
247
* Fetch the scancode.
248
*/
249
scancode = inb(KBD_DATA_REG);
250
scanstatus = inb(KBD_STATUS_REG);
251
252
/*
253
* Skip mouse input.
254
*/
255
if (scanstatus & KBD_STAT_MOUSE_OBF)
256
continue;
257
258
/*
259
* If we see 0xe0, this is either a break code for KP
260
* ENTER, or a repeat make for KP ENTER. Either way,
261
* since the second byte is equivalent to an ENTER,
262
* skip the 0xe0 and try again.
263
*
264
* If we see 0x1c, this must be a repeat ENTER or KP
265
* ENTER (and we swallowed 0xe0 before). Try again.
266
*
267
* We can also see make and break codes for other keys
268
* mashed before or after pressing ENTER. Thus, if we
269
* see anything other than 0x9c, we have to try again.
270
*
271
* Note, if you held some key as ENTER was depressed,
272
* that break code would get leaked out.
273
*/
274
if (scancode != 0x9c)
275
continue;
276
277
return;
278
}
279
}
280
281