概述
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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复