0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kdb.h>
0012 #include <linux/keyboard.h>
0013 #include <linux/ctype.h>
0014 #include <linux/io.h>
0015
0016
0017
0018 #define KBD_STATUS_REG 0x64
0019 #define KBD_DATA_REG 0x60
0020
0021
0022
0023 #define KBD_STAT_OBF 0x01
0024 #define KBD_STAT_MOUSE_OBF 0x20
0025
0026 static int kbd_exists;
0027 static int kbd_last_ret;
0028
0029
0030
0031
0032
0033
0034 int kdb_get_kbd_char(void)
0035 {
0036 int scancode, scanstatus;
0037 static int shift_lock;
0038 static int shift_key;
0039 static int ctrl_key;
0040 u_short keychar;
0041
0042 if (KDB_FLAG(NO_I8042) || KDB_FLAG(NO_VT_CONSOLE) ||
0043 (inb(KBD_STATUS_REG) == 0xff && inb(KBD_DATA_REG) == 0xff)) {
0044 kbd_exists = 0;
0045 return -1;
0046 }
0047 kbd_exists = 1;
0048
0049 if ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
0050 return -1;
0051
0052
0053
0054
0055 scancode = inb(KBD_DATA_REG);
0056 scanstatus = inb(KBD_STATUS_REG);
0057
0058
0059
0060
0061 if (scanstatus & KBD_STAT_MOUSE_OBF)
0062 return -1;
0063
0064
0065
0066
0067
0068
0069
0070
0071 if (((scancode&0x7f) == 0x2a) || ((scancode&0x7f) == 0x36)) {
0072
0073
0074
0075 if ((scancode & 0x80) == 0)
0076 shift_key = 1;
0077 else
0078 shift_key = 0;
0079 return -1;
0080 }
0081
0082 if ((scancode&0x7f) == 0x1d) {
0083
0084
0085
0086 if ((scancode & 0x80) == 0)
0087 ctrl_key = 1;
0088 else
0089 ctrl_key = 0;
0090 return -1;
0091 }
0092
0093 if ((scancode & 0x80) != 0) {
0094 if (scancode == 0x9c)
0095 kbd_last_ret = 0;
0096 return -1;
0097 }
0098
0099 scancode &= 0x7f;
0100
0101
0102
0103
0104
0105 if (scancode == 0x3a) {
0106
0107
0108
0109 shift_lock ^= 1;
0110
0111 #ifdef KDB_BLINK_LED
0112 kdb_toggleled(0x4);
0113 #endif
0114 return -1;
0115 }
0116
0117 if (scancode == 0x0e) {
0118
0119
0120
0121 return 8;
0122 }
0123
0124
0125 switch (scancode) {
0126 case 0xF:
0127 return 9;
0128 case 0x53:
0129 return 4;
0130 case 0x47:
0131 return 1;
0132 case 0x4F:
0133 return 5;
0134 case 0x4B:
0135 return 2;
0136 case 0x48:
0137 return 16;
0138 case 0x50:
0139 return 14;
0140 case 0x4D:
0141 return 6;
0142 }
0143
0144 if (scancode == 0xe0)
0145 return -1;
0146
0147
0148
0149
0150
0151
0152 if (scancode == 0x73)
0153 scancode = 0x59;
0154 else if (scancode == 0x7d)
0155 scancode = 0x7c;
0156
0157 if (!shift_lock && !shift_key && !ctrl_key) {
0158 keychar = plain_map[scancode];
0159 } else if ((shift_lock || shift_key) && key_maps[1]) {
0160 keychar = key_maps[1][scancode];
0161 } else if (ctrl_key && key_maps[4]) {
0162 keychar = key_maps[4][scancode];
0163 } else {
0164 keychar = 0x0020;
0165 kdb_printf("Unknown state/scancode (%d)\n", scancode);
0166 }
0167 keychar &= 0x0fff;
0168 if (keychar == '\t')
0169 keychar = ' ';
0170 switch (KTYP(keychar)) {
0171 case KT_LETTER:
0172 case KT_LATIN:
0173 if (isprint(keychar))
0174 break;
0175 fallthrough;
0176 case KT_SPEC:
0177 if (keychar == K_ENTER)
0178 break;
0179 fallthrough;
0180 default:
0181 return -1;
0182 }
0183
0184 if (scancode == 0x1c) {
0185 kbd_last_ret = 1;
0186 return 13;
0187 }
0188
0189 return keychar & 0xff;
0190 }
0191 EXPORT_SYMBOL_GPL(kdb_get_kbd_char);
0192
0193
0194
0195
0196
0197
0198 void kdb_kbd_cleanup_state(void)
0199 {
0200 int scancode, scanstatus;
0201
0202
0203
0204
0205
0206
0207 if (!kbd_last_ret)
0208 return;
0209
0210 kbd_last_ret = 0;
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 while (1) {
0226 while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
0227 cpu_relax();
0228
0229
0230
0231
0232 scancode = inb(KBD_DATA_REG);
0233 scanstatus = inb(KBD_STATUS_REG);
0234
0235
0236
0237
0238 if (scanstatus & KBD_STAT_MOUSE_OBF)
0239 continue;
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 if (scancode != 0x9c)
0258 continue;
0259
0260 return;
0261 }
0262 }