⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 一个用于学习的操作系统
💻 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 + -