[韦东山]嵌入式Linux应用开发 lecture7 输入系统应用编程

输入系统框架图:

数据流程:

① APP 发起read操作,若无数据则休眠;

② 用户操作设备,硬件上产生中断;

③ 输入系统驱动层对应的驱动程序处理中断: 读取到数据,转换为标准的输入事件,向核心层汇报;

④ 核心层可以决定把输入事件转发给上面哪个 handler 来处理;

(evdev_handler、kbd_handler、joydev_handler 等)

  evdev_handler(最常用):把 input_event 结构体保存在内核 buffer ,支持多个 APP 同时访问。

⑤ APP 对输入事件的处理;

APP 获 得 数 据 的 方 法 有 2 种 : 直 接 访 问 设 备 节 点 或者通过 tslib、libinput 这类库来间接 访问设备节点。

驱动程序:把数据从硬件设备传到APP(可以将同一硬件数据分发给多个APP)

APP得到的数据时一系列的输入事件

单个输入事件以“struct input_event”结构体表示

struct input_event{
    struct timeval time;      #时间
    __u16 type;               #哪类(如EV_KEY代表按键)
    __u16 code;               #哪个(如KEY_A)
    __s32 value;              #取值大小(如0-按下,1-松开)
}

struct timeval{
    __kernel_time_t    tv_sec;           #时间以秒表示
    __kernel_suseconds_t    tv_usec;     #时间以微秒表示
}

一份触摸屏数据:

同步事件“0000 0000 0000 0000”(type=code=value=0)会分隔开独立的完整事件。

输入设备:以“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)];    #支持哪类事件? key/rel/abs?
    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)];
}

查看输入设备的设备节点:ls /dev/input/* -l

查看设备节点对应的硬件信息:cat /proc/bus/input/devices

应用编程:使用ioctl( )查看输入设备的的硬件信息

#include <linux/input.h>
#include <sys/types.h>        //open()头文件
#include <sys/stat.h>         //open()头文件
#include <fcntl.h>            //open()头文件
#include <sys/ioctl.h>        //ioctl()头文件
#include <stdio.h>            //print()头文件


/* input:./01_get_input_info /dev/input/event0 */
int main(int argc, char **argv)
{
	int fd;
	int err;
	int len;
	int i;
	unsigned char byte;
	int bit;
	struct input_id id;
	unsigned int evbit[2];
	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);    //O_RDWR可读可写
	if (fd < 0)                    //无法打开
	{
		printf("open %s err\n", argv[1]);
		return -1;
	}

	err = ioctl(fd, EVIOCGID, &id);    //get id,需传入id地址才能对其操作
	if (err == 0)
	{
		printf("bustype = 0x%x\n", id.bustype );
		printf("vendor	= 0x%x\n", id.vendor  );
		printf("product = 0x%x\n", id.product );
		printf("version = 0x%x\n", id.version );
	}

	len = ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);   //get evbit设备支持的事件类型
	if (len > 0 && len <= sizeof(evbit))    //长度符合要求代表读取到数据,打印数据对应类型
	{
		printf("support ev type: ");
		for (i = 0; i < len; i++)
		{
			byte = ((unsigned char *)evbit)[i];
			for (bit = 0; bit < 8; bit++)
			{
				if (byte & (1<<bit)) {               //byte里的低bit位为1
					printf("%s ", ev_names[i*8 + bit]);
				}
			}
		}
		printf("\n");
	}

	return 0;
}

事件类型-事件名称对应表             不连续的值用NULL表示

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值