Why does `ioctl(fd, EVIOCGRAB, 1)` cause key spam sometimes?

一笑奈何 提交于 2019-12-22 00:27:00

问题


I'm trying to write my own "keyboard driver" (without actually writing a kernel module), by grabbing the keyboard at what I assume is the lowest level of abstraction in userland: /dev/input/event*.

The following code does the grabbing, provided you change the first ocurrence of ioctl(fd, EVIOCGRAB, UNGRAB) to ioctl(fd, EVIOCGRAB, GRAB).

// gcc main.c -o main

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <errno.h>

#define EXIT_KEY  KEY_ESC
#define UNGRAB    0
#define GRAB      1

const char* kbd_device = "/dev/input/event4";

// ------------------------------------------------------------------------------------------------
int main(void){
  int fd = open(kbd_device, O_RDONLY);
  if(fd == -1){
    printf("Cannot open %s. %s.\n", kbd_device, strerror(errno));
    return -1;
  }

  if(ioctl(fd, EVIOCGRAB, UNGRAB))
    printf("Couldn't grab %s. %s.\n", kbd_device, strerror(errno));
  else
    printf("Grabbed %s!\n", kbd_device);

  while(1){
    struct input_event event;
    read(fd, &event, sizeof(event));
    if (event.type == EV_KEY && event.value >= 0 && event.value <= 2){
      printf("%d %3d\n", event.value, event.code);

      if(event.code == EXIT_KEY){
        ioctl(fd, EVIOCGRAB, UNGRAB);
        close(fd);
        return 0;
      }

    }
  }
}

Problem

  • If I run gcc main.c -o main && sudo ./main, everything works as expected.
  • If first compile and then I run sudo ./main, however, the terminal scrolls down nonstop, as if the RETURN key was held down.

Why does happen?

Notes

  • I'm running Ubuntu 14.04
  • On my platform, /dev/input/event4 happens to be the keyboard

Motivation

I'm trying to write a keyboard "driver" that works both on X and not on X (eg. a TTY).

I understand X11's keyboard library/extension is XKB. I think the TTY's keyboard library is linux/divers/tty/vt/keyboard.c (source), the initial keyboard map it uses is in linux/drivers/tty/vt/defkeymap.map (source), and it can be modified by using loadkeys (source here). Do correct me if I'm wrong.


回答1:


When you type

gcc main.c -o main && sudo ./main ↵

GCC takes some time, so the key has been released by the time ./main runs.

When you type

sudo ./main ↵

the terminal sends the shell a newline as soon as you push down , and starts executing ./main. Then the released event is seen by your program, but not by your terminal, because your program has grabbed the input device. Thus, to the terminal it looks like is stuck down, so it continues to produce newlines.



来源:https://stackoverflow.com/questions/41995349/why-does-ioctlfd-eviocgrab-1-cause-key-spam-sometimes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!