📄 keyboard.c
字号:
//由吃肉的羊USRG提供
#include <fairysky/types.h>
#include <fairysky/defs.h>
#include <fairysky/kernel.h>
#include <fairysky/scheduler.h>
#include <fairysky/tty.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/memory.h>
//mode 是键盘特殊键的按下状态
//表示大小写转换键caps,交换键alt,控制键ctrl,换档键shift的状态
//位7caps down
//位5右alt down,位4左alt down,位3右ctrl down,位2左ctrl down 位1右shift down
//位0左shiftdown
static unsigned char mode = 0;
// 数字锁定键num-lock 大小写转换键caps-lock 滚动锁定键scroll-lock的LED发光管状态
//位7-3不用 位2 caps-lock 位1 num-lock(初始置1,) 位0 scroll-lock
static unsigned char leds;
//当扫描码是0xe0或0xe1时,置该标志。表示其后还跟随1个或2个字符扫描码
//位1 ==1收到0xe1标志,位0 ==1收到0xe0标志,
static unsigned char e0;
extern struct tty_queue *table_list[];
//按下shift之后的映射表
static unsigned char shift_map[] = {
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 127, 9,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 10, 0, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C',
'V', 'B', 'N', 'M', '<', '>', '?', 0, '\'', '*', 0, 32, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, '>', 0,
0, 0, 0, 0, 0, 0, 0, 0, 0
};
//普通的映射表
static unsigned char key_map[] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 127, 9,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', 0, 10, 0, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c',
'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, 32, 16, 1, 0, '-', 0, 0, 0,
'+', 0, 0, 0, 0, 0, 0, 0, '<', 10, 1, 0
};
//按下alt之后的映射表
static unsigned char alt_map[] = {
0, 0, 0, '@', 0, '$', 0, 0, '{', '[', ']', '}', '\\', 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, '~', 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
//功能键发送的扫描码
static long func_table[] = {
0x415b5b1b, 0x425b5b1b, 0x435b5b1b, 0x445b5b1b, 0x455b5b1b, 0x465b5b1b,
0x475b5b1b, 0x485b5b1b, 0x495b5b1b, 0x4a5b5b1b, 0x4b5b5b1b, 0x4c5b5b1b
};
static int do_self(int scancode);
static int uncaps(int scancode);
static int caps(int scancode);
static int lshift(int scancode);
static int rshift(int scancode);
static int unctrl(int scancode);
static int ctrl(int scancode);
static int none(int scancode);
static int num(int scancode);
static int minus(int scancode);
static int cursor(int scancode);
static int func(int scancode);
static int scroll(int scancode);
static int alt(int scancode);
static int unalt(int scancode);
static int unlshift(int scancode);
static int unrshift(int scancode);
static int setleds(void);
static int put_queue(long);
static int kbd_wait(void);
typedef int (*keyfn_ptr)();
static keyfn_ptr key_tab[] = {
none, do_self, do_self, do_self, /* 00-03 s0 esc 1 2 */
do_self, do_self, do_self, do_self, /* 04-07 3 4 5 6 */
do_self, do_self, do_self, do_self, /* 08-0B 7 8 9 0 */
do_self, do_self, do_self, do_self, /* 0C-0F + ' bs tab */
do_self, do_self, do_self, do_self, /* 10-13 q w e r */
do_self, do_self, do_self, do_self, /* 14-17 t y u i */
do_self, do_self, do_self, do_self, /* 18-1B o p } ^ */
do_self, ctrl, do_self, do_self, /* 1C-1F enter ctrl a s */
do_self, do_self, do_self, do_self, /* 20-23 d f g h */
do_self, do_self, do_self, do_self, /* 24-27 j k l | */
do_self, do_self, lshift, do_self, /* 28-2B { para lshift , */
do_self, do_self, do_self, do_self, /* 2C-2F z x c v */
do_self, do_self, do_self, do_self, /* 30-33 b n m , */
do_self, minus, rshift, do_self, /* 34-37 . - rshift * */
alt, do_self, caps, func, /* 38-3B alt sp caps f1 */
func, func, func, func, /* 3C-3F f2 f3 f4 f5 */
func, func, func, func, /* 40-43 f6 f7 f8 f9 */
func, num, scroll, cursor, /* 44-47 f10 num scr home */
cursor, cursor, do_self, cursor, /* 48-4B up pgup - left */
cursor, cursor, do_self, cursor, /* 4C-4F n5 right + end */
cursor, cursor, cursor, cursor, /* 50-53 dn pgdn ins del */
none, none, do_self, func, /* 54-57 sysreq ? < f11 */
func, none, none, none, /* 58-5B f12 ? ? ? */
none, none, none, none, /* 5C-5F ? ? ? ? */
none, none, none, none, /* 60-63 ? ? ? ? */
none, none, none, none, /* 64-67 ? ? ? ? */
none, none, none, none, /* 68-6B ? ? ? ? */
none, none, none, none, /* 6C-6F ? ? ? ? */
none, none, none, none, /* 70-73 ? ? ? ? */
none, none, none, none, /* 74-77 ? ? ? ? */
none, none, none, none, /* 78-7B ? ? ? ? */
none, none, none, none, /* 7C-7F ? ? ? ? */
none, none, none, none, /* 80-83 ? br br br */
none, none, none, none, /* 84-87 br br br br */
none, none, none, none, /* 88-8B br br br br */
none, none, none, none, /* 8C-8F br br br br */
none, none, none, none, /* 90-93 br br br br */
none, none, none, none, /* 94-97 br br br br */
none, none, none, none, /* 98-9B br br br br */
none, unctrl, none, none, /* 9C-9F br unctrl br br */
none, none, none, none, /* A0-A3 br br br br */
none, none, none, none, /* A4-A7 br br br br */
none, none, unlshift, none, /* A8-AB br br unlshift br */
none, none, none, none, /* AC-AF br br br br */
none, none, none, none, /* B0-B3 br br br br */
none, none, unrshift, none, /* B4-B7 br br unrshift br */
unalt, none, uncaps, none, /* B8-BB unalt br uncaps br */
none, none, none, none, /* BC-BF br br br br */
none, none, none, none, /* C0-C3 br br br br */
none, none, none, none, /* C4-C7 br br br br */
none, none, none, none, /* C8-CB br br br br */
none, none, none, none, /* CC-CF br br br br */
none, none, none, none, /* D0-D3 br br br br */
none, none, none, none, /* D4-D7 br br br br */
none, none, none, none, /* D8-DB br ? ? ? */
none, none, none, none, /* DC-DF ? ? ? ? */
none, none, none, none, /* E0-E3 e0 e1 ? ? */
none, none, none, none, /* E4-E7 ? ? ? ? */
none, none, none, none, /* E8-EB ? ? ? ? */
none, none, none, none, /* EC-EF ? ? ? ? */
none, none, none, none, /* F0-F3 ? ? ? ? */
none, none, none, none, /* F4-F7 ? ? ? ? */
none, none, none, none, /* F8-FB ? ? ? ? */
none, none, none, none /* FC-FF ? ? ? ? */
} ;
//数字小键盘数字键对应的数字ASCII码表
static unsigned char number_tab[] = {
'7', '8', '9', ' ', '4', '5', '6', ' ', '1', '2', '3', '0'
};
//数字小键盘方向键对应的数字ASCII码表
static unsigned char cursos_tab[] = "HA5 DGC YB623" ;
//键盘中断处理函数
#ifdef WINDOWS_CYGWIN
#define KBD_HANDLER kbd_handler
#else
#define KBD_HANDLER _kbd_handler
#endif
void KBD_HANDLER()
{
u8 scancode = inb_p(PORT_KBD_A);
if (scancode == 0xE0) {
e0 = 1;
} else if (scancode == 0xE1) {
e0 = 2;
} else {
key_tab[scancode](scancode);
e0 = 0;
}
outb_p((inb_p(0x61)) | 0x80, 0x61);
outb_p((inb_p(0x61)) & 0x7f, 0x61);
outb_p(EOI, PORT_8259M);
do_tty_interrupt(0);
}
int do_self(int scancode)
{
char *map;
unsigned char ch;
if (mode & 0x20) { // alt
map = alt_map;
} else if ((mode & 0x3)) { // shift ^ caps
map = shift_map;
} else {
map = key_map;
}
ch = map[scancode & 0xff];
if (ch == 0) {
return 0;
}
if ((mode & 0x4c)) {
//ctrl 或者caps
if (((mode & 0x41) == 0x41) ||
((mode & 0x42) == 0x42) ||
((mode & 0x43) == 0x43)) {
if ((ch <= 'Z' && ch >= 'A')) {
//shift 和 caps 都起作用,则字母小写
ch += 0x20 ;
}
} else if ((ch <= 'z' && ch >= 'a')) {
//如果只有 caps 都起作用,则字母大写
ch -= 0x20 ;
}
if (mode & 0xc) {
//如果按下ctrl,则加上ctrl标志
ch -= 0x40;
}
}
if (mode & 0x10) {
//如果按下alt,则加上alt标志
ch |= 0x80 ;
}
ch &= 0xff;
put_queue(ch);
return 0;
}
//按下alt
int alt(int scancode)
{
if (e0) {// right alt
mode |= 0x20;
} else {
mode |= 0x10;
}
return 0;
}
//放开alt
int unalt(int scancode)
{
if (e0) {
mode &= 0xdf;
} else {
mode &= 0xef;
}
return 0;
}
//按下ctrl
int ctrl(int scancode)
{
if (e0) {
mode |= 0x8;
} else {
mode |= 0x4;
}
return 0;
}
//放开ctrl
int unctrl(int scancode)
{
if (e0) {
mode &= 0xF7;
} else {
mode &= 0xFB;
}
return 0;
}
//按下左shift
int lshift(int scancode)
{
mode |= 0x1;
return 0;
}
//放开左shift
int unlshift(int scancode)
{
mode &= 0xfe;
return 0;
}
//按下右shift
int rshift(int scancode)
{
mode |= 0x2;
return 0;
}
//放开右shift
int unrshift(int scancode)
{
mode &= 0xfd;
return 0;
}
//按下caps
int caps(int scancode)
{
if (!(mode & 0x80)) {
leds ^= 0x4;
mode ^= 0x40;
mode |= 0x80;
setleds();
}
return 0;
}
//放开caps
int uncaps(int scancode)
{
mode &= 0x7f;
return 0;
}
//设置srcoll
int srcoll(int scancode)
{
leds |= 0x1;
setleds();
return 0;
}
//取消scroll
int scroll(int scancode)
{
leds ^= 0x1;
setleds();
return 0;
}
int num(int scancode)
{
leds ^= 0x2;
setleds();
return 0;
}
//方向键
int cursor(int scancode)
{
int i;
int ch;
// printk("cursor, scancode:%d\n", scancode);
i = scancode - 0x47 ; // 方向键从71开始
if (i < 0 || i > 12) {
return 0;
}
if ((e0 == 1) || (! (leds & 0x2)) || (mode & 0x3)) {// 小键盘上的数字键没有lock
ch = cursos_tab[i];
if (ch <= '9') {
ch = '~';
}
//形成移动序列
ch = ch << 16 | 0x5b1b;
} else { // 小键盘上的数字键
ch = number_tab[i];
}
put_queue(ch);
return 0;
}
//处理功能键
int func(int scancode)
{
int i = scancode - 59; //功能从59开始
if (i >= 0 && i <= 11) {// 12功能键
long ch ;
ch = func_table[i];
put_queue(ch);
}
return 0;
}
int minus(int scancode)
{
if (e0 != 1) {
do_self(scancode);
} else {
put_queue((long) '/');
}
return 0;
}
int setleds(void)
{
kbd_wait();
outb(0xed, 0x60);
kbd_wait();
outb(leds, 0x60);
return 0;
}
int kbd_wait(void)
{
while (inb_p(0x64) & 0x2) //kbd in buffer is full
;//do nothing
return 0;
}
int none(int scancode)
{
return 0;
}
//讲的到扫描码放入队列
static int put_queue(long ch)
{
struct tty_queue *q = table_list[0];
//printk("key:%c, key:%d\n", ch, ch);
while (ch) {
(q->buf)[q->head] = ch & 0xFF;
//printk("|ch: %c, %d|", (q->buf)[q->head], (q->buf)[q->head]);
q->head = (q->head + 1) & (TTY_BUF_SIZE - 1);
//printk("q->head:%d, q->tail: %d\n", q->head, q->tail);
if (q->head == q->tail) { // buf is full
return 0;
}
ch >>= 8;
}
wake_up(q->proc_list); //如果有等待该队列的进程,则唤醒
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -