代码之家  ›  专栏  ›  技术社区  ›  Michał Hanusek

虚拟键盘(Linux/libevdev)-发送事件

  •  2
  • Michał Hanusek  · 技术社区  · 8 年前

    正在尝试实现虚拟键盘。程序在5秒的周期内发送击键事件。它在PC(Ubuntu Linux)上工作。问题是Beaglebone Black/Raspberry Pi3上没有显示任何内容。

    debian@beaglebone:~$ uname -a
    Linux beaglebone 4.9.9-ti-r22 #1 SMP PREEMPT Mon Feb 13 18:39:00 UTC 2017 armv7l GNU/Linux
    

    代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <string.h>
    #include <linux/uinput.h>
    
    /* emit function is identical to of the first example */
    
    void emit(int fd, int type, int code, int val)
    {
       struct input_event ie;
    
       ie.type = type;
       ie.code = code;
       ie.value = val;
       /* timestamp values below are ignored */
       ie.time.tv_sec = 0;
       ie.time.tv_usec = 0;
    
       int res = write(fd, &ie, sizeof(ie));
       printf("emit write bytes=%d fd=%d code=%d val=%d\n",res, fd, code, val);
    }
    
    int main(void)
    {
       struct uinput_user_dev uud;
       int version, rc, fd;
    
       fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
       printf("fd=%d\n",fd);
    
       rc = ioctl(fd, UI_GET_VERSION, &version);
       printf("rd=%d\n",rc); 
    
       if (rc == 0 && version >= 5) 
       {
        printf("Error! version=%d\n",version);
          //return 0;
       }
    
       /*
        * The ioctls below will enable the device that is about to be
        * created, to pass key events, in this case the space key.
        */
       int i1 = ioctl(fd, UI_SET_EVBIT, EV_KEY);
       int i2 = ioctl(fd, UI_SET_EVBIT, EV_SYN);
       int i3 = ioctl(fd, UI_SET_KEYBIT, KEY_D);
       int i4 = ioctl(fd, UI_SET_KEYBIT, KEY_U);
       int i5 = ioctl(fd, UI_SET_KEYBIT, KEY_P);
       int i6 = ioctl(fd, UI_SET_KEYBIT, KEY_A);
    
    //  printf("ioctl = %d, %d, %d ,%d , %d, %d\n", i1,i2,i3,i4,i5,i6);
    
       memset(&uud, 0, sizeof(uud));
       snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "uinput-keyboard");
       uud.id.bustype = BUS_HOST;
       uud.id.vendor  = 0x1;
       uud.id.product = 0x2;
       uud.id.version = 1;
    
       write(fd, &uud, sizeof(uud));
       sleep(2);
    
       int i = ioctl(fd, UI_DEV_CREATE);
       printf("dev create =%d\n", i);
    
       sleep(2);
    
       /* Key press, report the event, send key release, and report again */
    for(;;)
    {
       emit(fd, EV_KEY, KEY_D, 1);
       emit(fd, EV_SYN, SYN_REPORT, 1);
       sleep(1);
       emit(fd, EV_KEY, KEY_D, 0);
       emit(fd, EV_SYN, SYN_REPORT, 0);
    
       emit(fd, EV_KEY, KEY_U, 1);
       emit(fd, EV_SYN, SYN_REPORT, 0);
       emit(fd, EV_KEY, KEY_U, 0);
       emit(fd, EV_SYN, SYN_REPORT, 0);
    
       emit(fd, EV_KEY, KEY_P, 1);
       emit(fd, EV_SYN, SYN_REPORT, 0);
       emit(fd, EV_KEY, KEY_P, 0);
       emit(fd, EV_SYN, SYN_REPORT, 0);
    
       emit(fd, EV_KEY, KEY_A, 1);
       emit(fd, EV_SYN, SYN_REPORT, 0);
       emit(fd, EV_KEY, KEY_A, 0);
       emit(fd, EV_SYN, SYN_REPORT, 0);
    
       sleep(5);
    }
       ioctl(fd, UI_DEV_DESTROY);
    
       close(fd);
       return 0;
    }
    

    lsinput-ev位是否正确

    /dev/input/event1
       bustype : BUS_HOST
       vendor  : 0x1
       product : 0x2
       version : 1
       name    : "uinput-keyboard"
       bits ev : (null) (null)
    

    root@beaglebone:/home/debian/KeyEvent# evtest
    No device specified, trying to scan all of /dev/input/event*
    Available devices:
    /dev/input/event0:  tps65217_pwr_but
    /dev/input/event1:  uinput-keyboard
    Select the device event number [0-1]: 1
    Input driver version is 1.0.1
    Input device ID: bus 0x19 vendor 0x1 product 0x2 version 0x1
    Input device name: "uinput-keyboard"
    Supported events:
      Event type 0 (EV_SYN)
      Event type 1 (EV_KEY)
        Event code 22 (KEY_U)
        Event code 25 (KEY_P)
        Event code 30 (KEY_A)
        Event code 32 (KEY_D)
    Properties:
    Testing ... (interrupt to exit)
    Event: time 1499869756.493690, type 1 (EV_KEY), code 32 (KEY_D), value 1
    Event: time 1499869756.493690, -------------- SYN_REPORT ------------
    Event: time 1499869757.494181, type 1 (EV_KEY), code 32 (KEY_D), value 0
    Event: time 1499869757.494181, -------------- SYN_REPORT ------------
    Event: time 1499869757.494304, type 1 (EV_KEY), code 22 (KEY_U), value 1
    Event: time 1499869757.494304, -------------- SYN_REPORT ------------
    Event: time 1499869757.494370, type 1 (EV_KEY), code 22 (KEY_U), value 0
    Event: time 1499869757.494370, -------------- SYN_REPORT ------------
    Event: time 1499869757.494434, type 1 (EV_KEY), code 25 (KEY_P), value 1
    Event: time 1499869757.494434, -------------- SYN_REPORT ------------
    Event: time 1499869757.494495, type 1 (EV_KEY), code 25 (KEY_P), value 0
    Event: time 1499869757.494495, -------------- SYN_REPORT ------------
    Event: time 1499869757.494558, type 1 (EV_KEY), code 30 (KEY_A), value 1
    Event: time 1499869757.494558, -------------- SYN_REPORT ------------
    Event: time 1499869757.499785, type 1 (EV_KEY), code 30 (KEY_A), value 0
    Event: time 1499869757.499785, -------------- SYN_REPORT ------------
    Event: time 1499869762.502378, type 1 (EV_KEY), code 32 (KEY_D), value 1
    Event: time 1499869762.502378, -------------- SYN_REPORT ------------
    Event: time 1499869763.225387, type 1 (EV_KEY), code 32 (KEY_D), value 0
    Event: time 1499869763.225402, -------------- SYN_REPORT ------------
    expected 16 bytes, got -1
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Michał Hanusek    8 年前

    我解决了这个问题。屏幕未连接到BeagleBone/Raspberry,系统无法将字符发送到屏幕。