Chinaunix首页 | 论坛 | 博客
  • 博客访问: 531693
  • 博文数量: 118
  • 博客积分: 3995
  • 博客等级: 中校
  • 技术积分: 1276
  • 用 户 组: 普通用户
  • 注册时间: 2005-11-15 12:15
文章分类

全部博文(118)

文章存档

2014年(1)

2013年(1)

2010年(6)

2009年(27)

2008年(10)

2007年(33)

2006年(38)

2005年(2)

我的朋友

分类: LINUX

2009-02-27 23:17:40

/*
 * Get data from the keyboard. If we finish a character, return it. Else 0.
 * Return -1 if no data.
 */

static int
kbd_proc_data(void)
{
        int c;
        uint8_t data;
        static uint32_t shift;    // 数据存在bss段中,这部分数据初始化为0,下次调用该函数时shift里的值还保存着

        
    // 读键盘控制状态寄存器0x64,如果第一位为1则表示有数据;KBSTATP,KBS_DIB在inc/kbdreg.h中定义

        if ((inb(KBSTATP) & KBS_DIB) == 0)
                return -1;
    
    //读键盘数据寄存器0x60

        data = inb(KBDATAP);

    /* 如果想知道键被按下和被释放时的键盘扫描码,可以加上一条输出语句输出码值,很直观!
        cprintf(" %02x ",data);
    */


        if (data == 0xE0) {
                // E0 escape character,扩展按键,扫描码为2字节;E0后面还跟有一个字节值

                shift |= E0ESC;
                return 0;
        } else if (data & 0x80) {    
                // Key released,除去E0,最高位为1(+0x80)的,应该是键释放的扫描码

         // 如果该扫描码是E0 escape的,那么保持值不变;否则清除最高位的1,其值

         // 变为建按下是的码值。这么做的目的就是为了处理左右ctrl,alt和shift键,

         // 即在建释放时清除其shiftcode值,因为它们的shiftcode值会影响其他字符

         // 的解析

                data = (shift & E0ESC ? data : data & 0x7F);
                shift &= ~(shiftcode[data] | E0ESC);    // 清除之前的shiftcode,表示

                                // 释放了ctrl,alt或者shift

                                // 如果该扫描码是E0 escape的

                                // 清除E0 escape标记

                return 0;
        } else if (shift & E0ESC) {
                 // Last character was an E0 escape; or with 0x80

         // 上一个字节值为E0,那么该字节应该是键被按下时扫描码的第二字节,

         // 让其与上0x80,用以后面处理时区分单字节扫描码

                data |= 0x80;
                shift &= ~E0ESC;    // 清除E0 escape

        }

        shift |= shiftcode[data];    // 键被按下时,置ctrl,alt和shift键被按下的状态

        shift ^= togglecode[data];    // CAPSLOCK,NUMLOCK,SCROLLLOCK这三个键没按一次,

                    // 它们的状态就改变(0,1变化),这里用异或巧妙的实现

                    // 它们的状态也会影响后面按键字符的解析


     // static uint8_t *charcode[4] = {normalmap,shiftmap,ctlmap,ctlmap};

     // CTL = 1 (01); SHIFT = 2 (10). CTL | SHIFT = 3 (11)

     // CTL和SHIFT二者组合值为0~3, 对应charcode里面的四个不同字符值map

        c = charcode[shift & (CTL | SHIFT)][data];
        if (shift & CAPSLOCK) {    // CAPSLOCK 影响字母字符解析

                if ('a' <= c && c <= 'z')    // 小写->大写

                        c += 'A' - 'a';
                else if ('A' <= c && c <= 'Z')    // 大写(shift键按下时)->小写

                        c += 'a' - 'A';
        }

        // Process special keys

        // Ctrl-Alt-Del: reboot

        if (!(~shift & (CTL | ALT)) && c == KEY_DEL) {
                cprintf("Rebooting!\n");
                outb(0x92, 0x3); // courtesy of Chris Frost

        // PS/2 POS, 0092: bit 1 = 1 indicates A20 active

        // bit 0 = 0 system reset or write

        //      1 pulse alternate reset pin (alternate CPU reset)

        }
        return c;
}

阅读(1048) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~