您现在的位置是:首页 > 服务器相关

操作系统设计之终端模块代码分析-键盘部分

2021-11-28服务器相关

简介操作系统设计,终端模块代码分析,键盘部分

键盘模块:

初始化键盘中断
PUBLIC void init_keyboard()
{
    kb_in.count = 0;
    kb_in.p_head = kb_in.p_tail = kb_in.buf;

    shift_l    = shift_r = 0;
    alt_l    = alt_r   = 0;
    ctrl_l    = ctrl_r  = 0;

        put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
        enable_irq(KEYBOARD_IRQ);                       /*开键盘中断*/
}


其中:
#define    KEYBOARD_IRQ    1

PUBLIC void keyboard_handler(int irq)
{
    u8 scan_code = in_byte(KB_DATA);

    if (kb_in.count < KB_IN_BYTES) {
        *(kb_in.p_head) = scan_code;
        kb_in.p_head++;
        if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
            kb_in.p_head = kb_in.buf;
        }
        kb_in.count++;
    }
}


#define KB_DATA        0x60
#define KB_CMD        0x64;


PUBLIC void keyboard_read()
{
    u8    scan_code;
    char    output[2];
    int    make;    /* 1: make;  0: break. */

    u32    key = 0;/* 用一个整型来表示一个键。比如,如果 Home 被按下,
             * 则 key 值将为定义在 keyboard.h 中的 'HOME'。
             */
    u32*    keyrow;    /* 指向 keymap[] 的某一行 */

    if(kb_in.count > 0){
        code_with_E0 = 0;

        scan_code = get_byte_from_kbuf();

        /* 下面开始解析扫描码 */
        if (scan_code == 0xE1) {
            int i;
            u8 pausebrk_scode[] = {0xE1, 0x1D, 0x45,0xE1, 0x9D, 0xC5};/*代表:PAUSE*/
            int is_pausebreak = 1;
            for(i=1;i<6;i++){
                if (get_byte_from_kbuf() != pausebrk_scode[i]) {
                    is_pausebreak = 0;
                    break;
                }
            }
            if (is_pausebreak) {
                key = PAUSEBREAK;
            }
        }
        else if (scan_code == 0xE0) {
            scan_code = get_byte_from_kbuf();

            /* PrintScreen 被按下 */
            if (scan_code == 0x2A) {                  /* 0x2A代表:SHIFT_L */
                if (get_byte_from_kbuf() == 0xE0) {     /* 0xE0代表: */
                    if (get_byte_from_kbuf() == 0x37) {   /* 0x37代表:* */
                        key = PRINTSCREEN;
                        make = 1;
                    }
                }
            }
            /* PrintScreen 被释放 */
            if (scan_code == 0xB7) {                  /* 0xB7代表: */
                if (get_byte_from_kbuf() == 0xE0) {     /* 0xE0代表: */
                    if (get_byte_from_kbuf() == 0xAA) {   /* 0xAA代表: */
                        key = PRINTSCREEN;
                        make = 0;
                    }
                }
            }
            /* 不是PrintScreen, 此时scan_code为0xE0紧跟的那个值. */
            if (key == 0) {
                code_with_E0 = 1;
            }
        }
        if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) {
            /* 首先判断Make Code 还是 Break Code */
            make = (scan_code & FLAG_BREAK ? 0 : 1);

            /* 先定位到 keymap 中的行 MAP_COLS=3 */
            keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];
            
            column = 0;
            if (shift_l || shift_r) {
                column = 1;
            }
            if (code_with_E0) {
                column = 2;
                code_with_E0 = 0;
            }
            
            /* 取keyrow第几行 */
            key = keyrow[column];
            
            switch(key) {
            case SHIFT_L:
                shift_l = make;
                break;
            case SHIFT_R:
                shift_r = make;
                break;
            case CTRL_L:
                ctrl_l = make;
                break;
            case CTRL_R:
                ctrl_r = make;
                break;
            case ALT_L:
                alt_l = make;
                break;
            case ALT_R:
                alt_l = make;
                break;
            default:
                break;
            }

            if (make) { /* 忽略 Break Code */
                key |= shift_l    ? FLAG_SHIFT_L    : 0;
                key |= shift_r    ? FLAG_SHIFT_R    : 0;
                key |= ctrl_l    ? FLAG_CTRL_L    : 0;
                key |= ctrl_r    ? FLAG_CTRL_R    : 0;
                key |= alt_l    ? FLAG_ALT_L    : 0;
                key |= alt_r    ? FLAG_ALT_R    : 0;
            
                in_process(key);
            }
        }
    }
}

PRIVATE u8 get_byte_from_kbuf()       /* 从键盘缓冲区中读取下一个字节 */
{
        u8 scan_code;

        while (kb_in.count <= 0) {}   /* 等待下一个字节到来 */

        disable_int();
        scan_code = *(kb_in.p_tail);
        kb_in.p_tail++;
        if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
                kb_in.p_tail = kb_in.buf;
        }
        kb_in.count--;
        enable_int();

        return scan_code;
}

PUBLIC void in_process(u32 key)
{
        char output[2] = {'\0', '\0'};

        if (!(key & FLAG_EXT)) {
                output[0] = key & 0xFF;
                disp_str(output);
        }
}


终端代码说明:
a键按下(make code)为0x1E 释放(break code)为0x9E
break code=make code|0x80
如果A则为(一般用左边shift):0x2A 0x1E 0x9E 0xAA,
对大写A分析:
按下shift键,则shift_l或shift_r变成1,column=1
再按下a键,程序找出keymap中a 那一行
弹起a键,则忽略
弹起shift键,则shift_l或shift_r变成0,column=0


欢迎大家加入我们gentoo技术群!


 

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

随便看看

文章排行

本栏推荐

栏目更新