返回顶部
首页 > 资讯 > 操作系统 >Linux系统struct input_event结构体分类型(鼠标、键盘、触屏)详解与例子
  • 683
分享到

Linux系统struct input_event结构体分类型(鼠标、键盘、触屏)详解与例子

linux运维服务器 2023-09-22 20:09:53 683人浏览 薄情痞子
摘要

目录 一、概述 二、结构体字段解析 三、不同类型地解释字段  3.1 鼠标事件  3.2 键盘事件  3.3 触摸屏事件 四、使用struct input_event读取设备文件的例子 一、概述 l

目录
一、概述
二、结构体字段解析
三、不同类型地解释字段
3.1 鼠标事件
3.2 键盘事件
3.3 触摸屏事件
四、使用struct input_event读取设备文件的例子


一、概述

linux系统是通过输入子系统来管理输入设备(如鼠标、键盘、触摸屏、游戏摇杆)的。配置了内核支持且安装对应驱动后,当系统接入输入设备,会在/dev/input下生成对应设备文件,下图是鼠标、键盘在不同情况下/dev/input的设备文件。
在这里插入图片描述
当输入设备有事件产生时,内核就会将事件上报到设备文件,事件的数据以struct input_event为单位存入设备文件,所以读取事件数据时使用struct input_event结构体,这个结构体定义在/usr/include/linux/input.h中,定义如下:

struct input_event {        struct timeval time;        __u16 type;        __u16 code;        __s32 value;};

二、结构体字段解析

  • time:事件产生的时间。

  • type:事件类型,常见的有:EV_KEY(键盘)、EV_REL(相对坐标)、EV_ABS(绝对坐标)、,定义在[input-event-codes.h] (https://GitHub.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#LC35) 或 input.h 中。
#define EV_SYN            0x00 #define EV_KEY            0x01 //按键#define EV_REL            0x02 //相对坐标(轨迹球)#define EV_ABS            0x03 //绝对坐标#define EV_MSC            0x04 //其他、杂项#define EV_SW             0x05 //软件#define EV_LED            0x11 //LED#define EV_SND            0x12 //声音#define EV_REP            0x14 //repeat、会自动发出重复按键#define EV_FF             0x15#define EV_PWR            0x16 //电源开关、按键#define EV_FF_STATUS      0x17#define EV_MAX            0x1f#define EV_CNT(EV_MAX+1)

  • code:事件的代码,对事件进一步的描述,如:
    键盘事件的键值(KEY_NUMLOCK、KEY_ESC、KEY_1、KEY_A),定义在[input-event-codes.h] (Https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h)、
    鼠标事件的位置信息(REL_X、REL_Y),滚轮信息(REL_WHEEL),定义在[input-event-codes.h] (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#LC812)、
    触摸屏事的地位置信息(ABS_MT_POSITioN_X),slot信息(ABS_MT_SLOT)定义在[input-event-codes.h] (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#LC839)

  • value:事件的值,对事件更具体地描述,如:
    按键的按下/抬起
    鼠标位置信息的具体 x值、y值
    触摸屏事件slot信息表示第几个的值、ABS_MT_TRACKING_ID的值

三、不同类型地解释字段

前面对 struct input_event 的四个字段有了简单的了解,这里通过读取一下实际事件来进一步了解这个结构体

3.1 鼠标事件

鼠标的事件一般有 EV_REL(相对坐标)、EV_KEY(按键) 两种类型,EV_REL用来表示鼠标在屏幕的位置,EV_KEY用来表示鼠标的按钮。下面读取一段鼠标事件的数据,分析鼠标的事件。
在这里插入图片描述

  • EV_REL类型(相对坐标)
    如果事件是相对坐标时,读取到的struct input_eventtype字段的值为 2
    code字段的取值可能是REL_X(相对坐标X值)、REL_X(相对坐标Y值)、REL_WHEEL(滚轮),
    value字段根据code的取值不同而不同,可以表示坐标(X值、Y值),滚轮上滑(-1)、下滑(1)
    下图是相对坐标时,code的定义的值
    在这里插入图片描述
  • EV_KEY类型(按键:左键、右键、滚轮键)
    鼠标事件也有按键类型,表示左键、右键、滚轮键按下/抬起,读取到的struct input_eventtype字段的值为 1
    code字段取值可能是BTN_LEFT(左键)、BTN_RIGHT(右键)、BTN_MIDDLE(滚轮键),
    value字段一般是 1 表示按下,0 表示抬起,
    下图是鼠标按键,code的定义的值
    在这里插入图片描述

3.2 键盘事件

键盘事件比较简单,它的事件类型一般EV_KEY,下面读取一段键盘事件进行分析
在这里插入图片描述
键盘事件的type字段一般为 EV_KEY (1),每次按键按下、抬起都有一个杂项类型EV_MSC(4),目前没什么用处;
code字段取值可能是为1到255,表示各个按键值,定义在定义在[input-event-codes.h] (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h)
value字段一般是 1 表示按下,0 表示抬起

3.3 触摸屏事件

触摸屏事件比较复杂,触摸屏协议A类协议、B类协议之分,具体的见之前这篇介绍触摸屏协议的文件文章,下面抓取一段B类协议触摸屏事件进行分析:
在这里插入图片描述
上面是在触摸屏右下角按下、抬起获取的事件数据,可以看出:触摸屏事件主要事件类型是EV_ABS(3);

code值在B类协议(多点触控)中主要有ABS_MT_SLOT(0x2f)、ABS_MT_TRACKING_ID(0x39)、ABS_MT_POSITION_X(0x35)、ABS_MT_POSITION_Y(0x36),这几个值的解析如下,
ABS_MT_SLOT:在多点触控中,与每个触点相关联,用来传播触点状态信息,value字段为0表示第一个触点
ABS_MT_TRACKING_ID:可跟踪ID,一个触点按下就会产生一个新的可跟踪ID,value值为-1表示该触点销毁
ABS_MT_POSITION_X:接触椭圆中心的表面 X 坐标,value值表示坐标数组
ABS_MT_POSITION_Y:接触椭圆中心的表面 Y 坐标,value值表示坐标数组

另外,触摸屏被按下/抬起会有一个按键类型,其code值为BTN_TOUCH(0x14a);

四、使用struct input_event读取设备文件的例子

下面是一个读取输入设备的例子,很详细,可以根据上面讲到的再结合例子进行理解,最重要的是多看input-event-codes.h文件,几乎所有与输入子系统相关的宏定义都在该文件里。

    #include   #include   #include   #include   #include   #include   #include   #include   #include   struct input_event event;  int main(int arGC, char **argv)  {      char          name[64];                 char          buf[256] = { 0, };        unsigned char mask[EV_MAX/8 + 1];       int           version;      int           fd = 0;      int           rc;      int           i, j;      char          *tmp;  #define test_bit(bit) (mask[(bit)/8] & (1 << ((bit)%8)))      for (i = 0; i < 32; i++) {          sprintf(name, "/dev/input/event%d", i);          if ((fd = open(name, O_RDONLY, 0)) >= 0) {              ioctl(fd, EVIOCGVERSION, &version);              ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);              ioctl(fd, EVIOCGBIT(0, sizeof(mask)), mask);              printf("%s\n", name);              printf("    evdev version: %d.%d.%d\n",                     version >> 16, (version >> 8) & 0xff, version & 0xff);              printf("    name: %s\n", buf);              printf("    features:");              for (j = 0; j < EV_MAX; j++) {                  if (test_bit(j)) {                      const char *type = "unknown";                      switch(j) {                      case EV_KEY: type = "keys/buttons"; break;                      case EV_REL: type = "relative";     break;                      case EV_ABS: type = "absolute";     break;                      case EV_MSC: type = "reserved";     break;                      case EV_LED: type = "leds";         break;                      case EV_SND: type = "sound";        break;                      case EV_REP: type = "repeat";       break;                      case EV_FF:  type = "feedback";     break;                      }                      printf(" %s", type);                  }              }              printf("\n");              close(fd);          }      }      if (argc > 1) {          sprintf(name, "/dev/input/event%d", atoi(argv[1]));          if ((fd = open(name, O_RDWR, 0)) >= 0) {              printf("%s: open, fd = %d\n", name, fd);              for (i = 0; i < LED_MAX; i++) {                  event.time.tv_sec  = time(0);                  event.time.tv_usec = 0;                  event.type         = EV_LED;                  event.code         = i;                  event.value        = 0;                  write(fd, &event, sizeof(event));              }              while ((rc = read(fd, &event, sizeof(event))) > 0) {                  printf("%-24.24s.%06lu type 0x%04x; code 0x%04x;"                         " value 0x%08x; ",                         ctime(&event.time.tv_sec),                         event.time.tv_usec,                         event.type, event.code, event.value);                  switch (event.type) {                  case EV_KEY:                      if (event.code > BTN_MISC) {                          printf("Button %d %s",     event.code & 0xff,     event.value ? "press" : "release");                      } else {                          printf("Key %d (0x%x) %s",     event.code & 0xff,     event.code & 0xff,     event.value ? "press" : "release");                      }                      break;                  case EV_REL:                      switch (event.code) {                      case REL_X:      tmp = "X";       break;                      case REL_Y:      tmp = "Y";       break;                      case REL_HWHEEL: tmp = "HWHEEL";  break;                      case REL_DIAL:   tmp = "DIAL";    break;                      case REL_WHEEL:  tmp = "WHEEL";   break;                      case REL_MISC:   tmp = "MISC";    break;                      default:         tmp = "UNKNOWN"; break;                      }                      printf("Relative %s %d", tmp, event.value);                      break;                  case EV_ABS:                      switch (event.code) {                      case ABS_X:        tmp = "X";        break;                      case ABS_Y:        tmp = "Y";        break;                      case ABS_Z:        tmp = "Z";        break;                      case ABS_RX:       tmp = "RX";       break;                      case ABS_RY:       tmp = "RY";       break;                      case ABS_RZ:       tmp = "RZ";       break;                      case ABS_THROTTLE: tmp = "THROTTLE"; break;                      case ABS_RUDDER:   tmp = "RUDDER";   break;                      case ABS_WHEEL:    tmp = "WHEEL";    break;                      case ABS_GAS:      tmp = "GAS";      break;                      case ABS_BRAKE:    tmp = "BRAKE";    break;                      case ABS_HAT0X:    tmp = "HAT0X";    break;                      case ABS_HAT0Y:    tmp = "HAT0Y";    break;                      case ABS_HAT1X:    tmp = "HAT1X";    break;                      case ABS_HAT1Y:    tmp = "HAT1Y";    break;                      case ABS_HAT2X:    tmp = "HAT2X";    break;                      case ABS_HAT2Y:    tmp = "HAT2Y";    break;                      case ABS_HAT3X:    tmp = "HAT3X";    break;                      case ABS_HAT3Y:    tmp = "HAT3Y";    break;                      case ABS_PRESSURE: tmp = "PRESSURE"; break;                      case ABS_DISTANCE: tmp = "DISTANCE"; break;                      case ABS_TILT_X:   tmp = "TILT_X";   break;                      case ABS_TILT_Y:   tmp = "TILT_Y";   break;                      case ABS_MISC:     tmp = "MISC";     break;  case ABS_MT_SLOT:  tmp = "MT_SLOT";     break;  case ABS_MT_TRACKING_ID: tmp = "MT_TRACKING_ID";     break;  case ABS_MT_POSITION_X:  tmp = "MT_X";     break;  case ABS_MT_POSITION_Y:  tmp = "MT_Y";     break;                      default:           tmp = "UNKNOWN";  break;                      }                      printf("Absolute %s %d", tmp, event.value);                      break;                  case EV_MSC: printf("Misc"); break;                  case EV_LED: printf("Led");  break;                  case EV_SND: printf("Snd");  break;                  case EV_REP: printf("Rep");  break;                  case EV_FF:  printf("FF");   break;                      break;                  }                  printf("\n");              }              printf("rc = %d, (%s)\n", rc, strerror(errno));              close(fd);          }      }      return 0;  }

如果文章对你有帮助,请点赞、收藏支持一下 !!! *_^

来源地址:https://blog.csdn.net/wkd_007/article/details/126729030

--结束END--

本文标题: Linux系统struct input_event结构体分类型(鼠标、键盘、触屏)详解与例子

本文链接: https://lsjlt.com/news/415782.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作