键盘笔划连续键未捕获

时间:2013-12-07 05:14:04

标签: linux-kernel keyboard

这是一项任务,我编写了一个Linux驱动程序,我们必须捕获关键笔划。

我们将任务分为上半部分和下半部分(工作队列)。我能够像a,b,1,2等那样正确记录正常的键击,但是当我们长按任何一个字符时,它会记录7个额外的字母。

例如,当我连续按下(a)像aaa我的日志文件显示aaaaaaaaa时,它会回声7个额外的a。

有人可以说出可能是根本原因吗?

编辑#1

工作队列代码

// WORK QUEUE
static void got_char(my_work_cls *work_str)
{
    char fileinfo_buff[200], path[120];
    strcpy(fileinfo_buff,"");
    printk(KERN_INFO "Scan Code %d %x %s.\n",
    work_str->scancode,
    work_str->scancode & 0x7F,
    work_str->scancode & 0x80 ? "Released" : "Pressed");
    if(!(work_str->scancode & 0x80))
    {
        printk(KERN_INFO "Scancode BFSHFT=%s ",key[work_str->scancode]);
        if(work_str->scancode==42 || work_str->scancode==54 ||  shpress==1)
        {
            if(shpress==1 && ( work_str->scancode!=42 || work_str->scancode!=54) )
            {
                   if(((work_str->scancode)+70)<=len)
                   {
                      printk(KERN_INFO "Scancode SHFT=%s",key[(work_str->scancode)+70]);
                      strcat(fileinfo_buff,key[(work_str->scancode)+70]);      
                   }
            }
            shpress=1;
        }
        else
        {   
            if(work_str->scancode==28)
            {
                printk(KERN_INFO "Scancode En=%s",key[work_str->scancode]);
                strcat(fileinfo_buff,"\n");         
            }
            else
            {
                printk(KERN_INFO "Scancode S=%s",key[work_str->scancode]);
                strcat(fileinfo_buff,key[work_str->scancode]);
            }   
    }

    }
    else
    {
        if(((work_str->scancode)-128)==42 || ((work_str->scancode)-128)==54)
        {
            printk(KERN_INFO "Scancode RL=%s",key[((work_str->scancode)-128)]);
            shpress=0;
        }
    }   

}

中断处理程序代码

// interrupt handler

irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
     /*
     * This variables are static because they need to be
     * accessible (through pointers) to the bottom half routine.
     */
     static int initialised = 0;
     static unsigned char scancode;
     static struct work_struct task;
     unsigned char status;

     /*
     * Read keyboard status 
     */
     status = inb(0x64);
     scancode = inb(0x60);

     printk(KERN_INFO "In F Scancode=%d",scancode);
     work_str = (my_work_cls *)kmalloc(sizeof(my_work_cls), GFP_KERNEL);
     if (initialised == 0) 
     {
        printk(KERN_INFO "If Scancode=%d",scancode);

        if (work_str) 
        {
           INIT_WORK((struct work_struct *)work_str, got_char);
           work_str->scancode = scancode;
           initialised = 1;
        } 
     }
     else 
     {
        PREPARE_WORK((struct work_struct *)work_str, got_char);
         work_str->scancode = scancode;
     }
     queue_work(my_workqueue, (struct work_struct *)work_str);

     return IRQ_HANDLED;
 }

1 个答案:

答案 0 :(得分:0)

内核驱动程序中记录的每个 a 表示从硬件收到的关键事件。

Hardware -> Kernel-Driver -> Display server -> Window manager -> App -> Screen

在GUI系统上,用户空间显示服务器,窗口管理器和应用程序可以自由选择忽略keyevent。这通常是为了消除意外的长按键被识别为多个按键。

在X上,选项AutoRepeat <delay> <rate>设置键盘的自动重复行为。 延迟是密钥开始重复之前的时间(以毫秒为单位) 费率是密钥每秒重复的次数。

例如 Autorepeat 500 30 将X配置为:
   - 忽略来自硬件的keyevent(相同密钥)500ms    - 在500ms之后,每30ms只接受一个(相同键的)键事件。

另外,任何不同硬件密钥的keyevent都会重新启动整个过程以计算自动重复。

注意:这种自动重复延迟和速率限制通常也在应用程序本身中实现。因此,即使没有X,通常也会观察到内核键盘驱动程序报告的键数与应用程序中屏幕上显示的文本之间的差异。

相关问题