我是靠谱客的博主 玩命冰棍,最近开发中收集的这篇文章主要介绍linux输入设备-应用程序如何获取到id及evbit,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

linux中每一个输入设备都用一个struct input_dev来表示

struct input_dev {
    const char *name;
    const char *phys;
    const char *uniq;
    struct input_id id;

    unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

    unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//evbit表示设备支持哪一个类型的输入事件
    unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
    unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
    unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
    unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
    unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
    unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
    unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
    unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

在这里我们主要要关注应用程序如何获取到id及evbit

在linux内核evdev.c中存在evdev_do_ioctl结构体

static long evdev_do_ioctl(struct file *file, unsigned int cmd,
               void __user *p, int compat_mode)

case EVIOCGVERSION://获得版本号

case EVIOCGID://获得ID

ID内容有:

struct input_id {
    __u16 bustype;//总线类型
    __u16 vendor;//厂商
    __u16 product;
    __u16 version;
};

case EVIOCGREP: if (!test_bit(EV_REP, dev->evbit))

我们比较关心的是此处的dev->evbit表示这个设备支持哪个类型的输入事件

EVIOCGVERSION EVIOCGID EVIOCGREP这些宏在哪?在内核input.h内我们应该包含此头文件,但是不是直接包含,而更应该关注我们的工具链里这些宏在哪?

 先进入内核所在目录,在执行find -name input.h即可

获取输入设备id在应用程序中    

struct input_id id;

    ret = ioctl(fd,EVIOCGID,&id);//case EVIOCGID://获得ID的宏
    if ( ret == 0)
    {
        printf("bustype = 0x%xn",id.bustype);
        printf("vendor  = 0x%xn",id.vendor);
        printf("product = 0x%xn",id.product);
        printf("version = 0x%xn",id.version);
    }

即可将输入设备的id信息打印出来

获取输入设备evbit相对复杂,首先在内核源码input-event-codes.h中有描述evbit类型的宏

#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
#define EV_SND            0x12
#define EV_REP            0x14
#define EV_FF            0x15
#define EV_PWR            0x16

为了在应用层打印支持哪些事件,先将这些宏定义到一个char *ev_names[]数组中对于

缺少的0x06,0x07...0x10  0x13这些我们可以设为NULL

    char *ev_names[] = {
 "EV_SYN"   ,    
 "EV_KEY"   ,    
 "EV_REL"   ,    
 "EV_ABS"   ,    
 "EV_MSC"   ,    
 "EV_SW"    ,    
 "NULL"        ,    
 "NULL"        ,    
 "NULL"        ,    
 "NULL"        ,   
 "NULL"        ,    
 "NULL"     ,   
 "NULL"        ,   
 "NULL"        ,    
 "NULL"        ,    
 "NULL"     ,    
 "NULL"        ,    
 "EV_LED"    ,    
 "EV_SND"    ,    
 "NULL"        ,   
 "EV_REP"    ,
 "EV_FF"    ,    
 "EV_PWR"    ,    
};

 接下来调用ioctl来将数据放入evbit

unsigned int evbit[2];//8个字节用于存放evbit,这个其实多了,从上面的ev_names数组可以看到

事件一共也就不到2byte,而我们用了8byte,而这都随意
 int len;

/*0表示读evbit,读的大小sizeof(evbit),&evbit表示读到evbit*/
    len = ioctl(fd,EVIOCGBIT(0,sizeof(evbit)),&evbit);//返回值为byte数

接下来就是解析了

    if( len > 0 && len <= sizeof(evbit))  //ifioctl成功
    {
        printf("Suppport ev type:");
        for( i = 0; i < len;i++)                //目的把每一个byte都一个一个取出来(有8byte)
        {
            byte = ((unsigned char *)evbit)[i]; //将其中一个byte取出来
            for (bit = 0;bit < 8;bit++)        //比较byte的8个bit是0 or 1
            {
                if ( byte & (1<<bit))        //如果为1则表示支持这种类型的输入事件
                {
                    printf("%s ",ev_names[i*8 + bit]);

//i * 8是因为一个byte有8bit,下一个byte的bit时要与输入事件类型相匹配
                }
            }
        }
        printf("n");
    }

完整代码:

#include <linux/input.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>

/*eg:  ./01_get_input_info   /dev/input/event0  */
int main(int argc,char **argv)
{
    int fd;
    int ret;
    struct input_id id;
    unsigned int evbit[2];
    int len;
    int i;
    unsigned char byte;
    int bit;
    char *ev_names[] = {
 "EV_SYN"   ,    
 "EV_KEY"   ,    
 "EV_REL"   ,    
 "EV_ABS"   ,    
 "EV_MSC"   ,    
 "EV_SW"    ,    
 "NULL"        ,    
 "NULL"        ,    
 "NULL"        ,    
 "NULL"        ,   
 "NULL"        ,    
 "NULL"     ,   
 "NULL"        ,   
 "NULL"        ,    
 "NULL"        ,    
 "NULL"     ,    
 "NULL"        ,    
 "EV_LED"    ,    
 "EV_SND"    ,    
 "NULL"        ,   
 "EV_REP"    ,
 "EV_FF"    ,    
 "EV_PWR"    ,    
};

    if ( argc != 2 )
    {
        printf("Usage :%s <dev>n",argv[0]);
        return -1;
    }

    fd  = open(argv[1],O_RDWR);
    if ( fd < 0)
    {
        printf("Open %s err!n",argv[1]);
        return -1;    
    }

    ret = ioctl(fd,EVIOCGID,&id);
    if ( ret == 0)
    {
        printf("bustype = 0x%xn",id.bustype);
        printf("vendor  = 0x%xn",id.vendor);
        printf("product = 0x%xn",id.product);
        printf("version = 0x%xn",id.version);
    }

/*0表示读evbit,读的大小sizeof(evbit),&evbit表示读到evbit*/
    len = ioctl(fd,EVIOCGBIT(0,sizeof(evbit)),&evbit);
    if( len > 0 && len <= sizeof(evbit))
    {
        printf("Suppport ev type:");
        for( i = 0; i < len;i++)
        {
            byte = ((unsigned char *)evbit)[i];
            for (bit = 0;bit < 8;bit++)
            {
                if ( byte & (1<<bit))
                {
                    printf("%s ",ev_names[i*8 + bit]);
                }
            }
        }
        printf("n");
    }
    return 0;
}
在linux下编译执行:

arm-buildroot-linux-gnueabihf-gcc -o 01_get_input_info get_input_info.c -Wall

cp 01_get_input_info ~/nfs_rootfs/

再打开板子的串口,挂载nfs执行:

mount -t nfs -o nolock,vers=3 192.168.31.147:/home/book/nfs_rootfs /mnt


cd /mnt/

 

用 cat /proc/bus/input/devices查看是否正确

 EV=3表示:11即支持EV_SYN   EV_KEY两种输入事件

 

最后

以上就是玩命冰棍为你收集整理的linux输入设备-应用程序如何获取到id及evbit的全部内容,希望文章能够帮你解决linux输入设备-应用程序如何获取到id及evbit所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部