文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-09-22 20:48

关注

目录
一、概述
二、结构体字段解析
三、不同类型地解释字段
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;};

二、结构体字段解析


#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)


三、不同类型地解释字段

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

3.1 鼠标事件

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

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯