📄 keyboard.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/keyboard.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13000 /* Keyboard driver for PC's and AT's.
13001 *
13002 * Changed by Marcus Hampel (04/02/1994)
13003 * - Loadable keymaps
13004 */
13005
13006 #include "kernel.h"
13007 #include <termios.h>
13008 #include <signal.h>
13009 #include <unistd.h>
13010 #include <minix/callnr.h>
13011 #include <minix/com.h>
13012 #include <minix/keymap.h>
13013 #include "tty.h"
13014 #include "keymaps/us-std.src"
13015
13016 /* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */
13017 #define KEYBD 0x60 /* I/O port for keyboard data */
13018
13019 /* AT keyboard. */
13020 #define KB_COMMAND 0x64 /* I/O port for commands on AT */
13021 #define KB_GATE_A20 0x02 /* bit in output port to enable A20 line */
13022 #define KB_PULSE_OUTPUT 0xF0 /* base for commands to pulse output port */
13023 #define KB_RESET 0x01 /* bit in output port to reset CPU */
13024 #define KB_STATUS 0x64 /* I/O port for status on AT */
13025 #define KB_ACK 0xFA /* keyboard ack response */
13026 #define KB_BUSY 0x02 /* status bit set when KEYBD port ready */
13027 #define LED_CODE 0xED /* command to keyboard to set LEDs */
13028 #define MAX_KB_ACK_RETRIES 0x1000 /* max #times to wait for kb ack */
13029 #define MAX_KB_BUSY_RETRIES 0x1000 /* max #times to loop while kb busy */
13030 #define KBIT 0x80 /* bit used to ack characters to keyboard */
13031
13032 /* Miscellaneous. */
13033 #define ESC_SCAN 1 /* Reboot key when panicking */
13034 #define SLASH_SCAN 53 /* to recognize numeric slash */
13035 #define HOME_SCAN 71 /* first key on the numeric keypad */
13036 #define DEL_SCAN 83 /* DEL for use in CTRL-ALT-DEL reboot */
13037 #define CONSOLE 0 /* line number for console */
13038 #define MEMCHECK_ADR 0x472 /* address to stop memory check after reboot */
13039 #define MEMCHECK_MAG 0x1234 /* magic number to stop memory check */
13040
13041 #define kb_addr() (&kb_lines[0]) /* there is only one keyboard */
13042 #define KB_IN_BYTES 32 /* size of keyboard input buffer */
13043
13044 PRIVATE int alt1; /* left alt key state */
13045 PRIVATE int alt2; /* right alt key state */
13046 PRIVATE int capslock; /* caps lock key state */
13047 PRIVATE int esc; /* escape scan code detected? */
13048 PRIVATE int control; /* control key state */
13049 PRIVATE int caps_off; /* 1 = normal position, 0 = depressed */
13050 PRIVATE int numlock; /* number lock key state */
13051 PRIVATE int num_off; /* 1 = normal position, 0 = depressed */
13052 PRIVATE int slock; /* scroll lock key state */
13053 PRIVATE int slock_off; /* 1 = normal position, 0 = depressed */
13054 PRIVATE int shift; /* shift key state */
13055
13056 PRIVATE char numpad_map[] =
13057 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
13058
13059 /* Keyboard structure, 1 per console. */
13060 struct kb_s {
13061 char *ihead; /* next free spot in input buffer */
13062 char *itail; /* scan code to return to TTY */
13063 int icount; /* # codes in buffer */
13064 char ibuf[KB_IN_BYTES]; /* input buffer */
13065 };
13066
13067 PRIVATE struct kb_s kb_lines[NR_CONS];
13068
13069 FORWARD _PROTOTYPE( int kb_ack, (void) );
13070 FORWARD _PROTOTYPE( int kb_wait, (void) );
13071 FORWARD _PROTOTYPE( int func_key, (int scode) );
13072 FORWARD _PROTOTYPE( int scan_keyboard, (void) );
13073 FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
13074 FORWARD _PROTOTYPE( void set_leds, (void) );
13075 FORWARD _PROTOTYPE( int kbd_hw_int, (int irq) );
13076 FORWARD _PROTOTYPE( void kb_read, (struct tty *tp) );
13077 FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
13078
13079
13080 /*===========================================================================*
13081 * map_key0 *
13082 *===========================================================================*/
13083 /* Map a scan code to an ASCII code ignoring modifiers. */
13084 #define map_key0(scode) \
13085 ((unsigned) keymap[(scode) * MAP_COLS])
13086
13087
13088 /*===========================================================================*
13089 * map_key *
13090 *===========================================================================*/
13091 PRIVATE unsigned map_key(scode)
13092 int scode;
13093 {
13094 /* Map a scan code to an ASCII code. */
13095
13096 int caps, column;
13097 u16_t *keyrow;
13098
13099 if (scode == SLASH_SCAN && esc) return '/'; /* don't map numeric slash */
13100
13101 keyrow = &keymap[scode * MAP_COLS];
13102
13103 caps = shift;
13104 if (numlock && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
13105 if (capslock && (keyrow[0] & HASCAPS)) caps = !caps;
13106
13107 if (alt1 || alt2) {
13108 column = 2;
13109 if (control || alt2) column = 3; /* Ctrl + Alt1 == Alt2 */
13110 if (caps) column = 4;
13111 } else {
13112 column = 0;
13113 if (caps) column = 1;
13114 if (control) column = 5;
13115 }
13116 return keyrow[column] & ~HASCAPS;
13117 }
13120 /*===========================================================================*
13121 * kbd_hw_int *
13122 *===========================================================================*/
13123 PRIVATE int kbd_hw_int(irq)
13124 int irq;
13125 {
13126 /* A keyboard interrupt has occurred. Process it. */
13127
13128 int code;
13129 unsigned km;
13130 register struct kb_s *kb;
13131
13132 /* Fetch the character from the keyboard hardware and acknowledge it. */
13133 code = scan_keyboard();
13134
13135 /* The IBM keyboard interrupts twice per key, once when depressed, once when
13136 * released. Filter out the latter, ignoring all but the shift-type keys.
13137 * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
13138 */
13139
13140 if (code & 0200) {
13141 /* A key has been released (high bit is set). */
13142 km = map_key0(code & 0177);
13143 if (km != CTRL && km != SHIFT && km != ALT && km != CALOCK
13144 && km != NLOCK && km != SLOCK && km != EXTKEY)
13145 return 1;
13146 }
13147
13148 /* Store the character in memory so the task can get at it later. */
13149 kb = kb_addr();
13150 if (kb->icount < KB_IN_BYTES) {
13151 *kb->ihead++ = code;
13152 if (kb->ihead == kb->ibuf + KB_IN_BYTES) kb->ihead = kb->ibuf;
13153 kb->icount++;
13154 tty_table[current].tty_events = 1;
13155 force_timeout();
13156 }
13157 /* Else it doesn't fit - discard it. */
13158 return 1; /* Reenable keyboard interrupt */
13159 }
13162 /*==========================================================================*
13163 * kb_read *
13164 *==========================================================================*/
13165 PRIVATE void kb_read(tp)
13166 tty_t *tp;
13167 {
13168 /* Process characters from the circular keyboard buffer. */
13169
13170 struct kb_s *kb;
13171 char buf[3];
13172 int scode;
13173 unsigned ch;
13174
13175 kb = kb_addr();
13176 tp = &tty_table[current]; /* always use the current console */
13177
13178 while (kb->icount > 0) {
13179 scode = *kb->itail++; /* take one key scan code */
13180 if (kb->itail == kb->ibuf + KB_IN_BYTES) kb->itail = kb->ibuf;
13181 lock();
13182 kb->icount--;
13183 unlock();
13184
13185 /* Function keys are being used for debug dumps. */
13186 if (func_key(scode)) continue;
13187
13188 /* Perform make/break processing. */
13189 ch = make_break(scode);
13190
13191 if (ch <= 0xFF) {
13192 /* A normal character. */
13193 buf[0] = ch;
13194 (void) in_process(tp, buf, 1);
13195 } else
13196 if (HOME <= ch && ch <= INSRT) {
13197 /* An ASCII escape sequence generated by the numeric pad. */
13198 buf[0] = ESC;
13199 buf[1] = '[';
13200 buf[2] = numpad_map[ch - HOME];
13201 (void) in_process(tp, buf, 3);
13202 } else
13203 if (ch == ALEFT) {
13204 /* Choose lower numbered console as current console. */
13205 select_console(current - 1);
13206 } else
13207 if (ch == ARIGHT) {
13208 /* Choose higher numbered console as current console. */
13209 select_console(current + 1);
13210 } else
13211 if (AF1 <= ch && ch <= AF12) {
13212 /* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
13213 select_console(ch - AF1);
13214 }
13215 }
13216 }
13219 /*===========================================================================*
13220 * make_break *
13221 *===========================================================================*/
13222 PRIVATE unsigned make_break(scode)
13223 int scode; /* scan code of key just struck or released */
13224 {
13225 /* This routine can handle keyboards that interrupt only on key depression,
13226 * as well as keyboards that interrupt on key depression and key release.
13227 * For efficiency, the interrupt routine filters out most key releases.
13228 */
13229 int ch, make;
13230 static int CAD_count = 0;
13231
13232 /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
13233 * be better done in keyboard() in case TTY is hung, except control and
13234 * alt are set in the high level code.
13235 */
13236 if (control && (alt1 || alt2) && scode == DEL_SCAN)
13237 {
13238 if (++CAD_count == 3) wreboot(RBT_HALT);
13239 cause_sig(INIT_PROC_NR, SIGABRT);
13240 return -1;
13241 }
13242
13243 /* High-order bit set on key release. */
13244 make = (scode & 0200 ? 0 : 1); /* 0 = release, 1 = press */
13245
13246 ch = map_key(scode & 0177); /* map to ASCII */
13247
13248 switch (ch) {
13249 case CTRL:
13250 control = make;
13251 ch = -1;
13252 break;
13253 case SHIFT:
13254 shift = make;
13255 ch = -1;
13256 break;
13257 case ALT:
13258 if (make) {
13259 if (esc) alt2 = 1; else alt1 = 1;
13260 } else {
13261 alt1 = alt2 = 0;
13262 }
13263 ch = -1;
13264 break;
13265 case CALOCK:
13266 if (make && caps_off) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -