【嵌入式应用开发基础之使用 poll 函数监测多个输入设备】

@[TOC](使用 poll 函数监测多个输入设备)

Imx9ull开发板实验现象

  • 输入硬件信息
    输入硬件信息
  • 实验现象
    实验现象
    每次按键按下ret = 1,说明两个输入设备只有一个触发了EV_KEY事件

代码

#include <linux/input.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/ioctl.h>

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <poll.h>



/* ./02_input_read /dev/input/event0 noblock]*/
int	main(int argc,char **argv)
{
	int fd;
	int err;
	int len;
	int i;
	unsigned char byte;
	int bit;
	struct input_event event;

	struct pollfd fds[2];
	nfds_t nfds = 2;
	int timeout_ms = 5000;

	int ret = 0;

	
	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",
		"EV_LED",//0x11 = 17D 
		"EV_SND",
		"NULL",
		"EV_REP",
		"EV_FF ",
		"EV_PWR",
	};
	
	if (argc == nfds + 1)
	{
		for	(int i = 0;i < nfds; i++)
		{
			/* 打开文件 */
			fd = open(argv[i+1],O_RDWR | O_NONBLOCK);//非阻塞模式->查询
			if (fd < 0)
			{
				printf("open %s err\n",argv[i+1]);
			}
			/* 获取文件信息,并打印*/
			err = ioctl(fd,EVIOCGID,&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);//取出来几个字节的数据
			printf("len = %d\n",len);
			if (len > 0 && len <= sizeof(evbit))
			{
				printf("%s support ev type: ",argv[i+1]);
				for (int j= 0; j< len; j++)
				{
					byte = ((unsigned char *)evbit)[j];
					for (bit = 0; bit < 8; bit++)
					{
						if (byte & (1<<bit)){
							printf("%s ", ev_names[j*8 + bit]);
						}
					}
				}
			printf("\n");
			}
			
			/* 设置poll的文件描述符与关注的事件信息 */
			fds[i].fd = fd;
			fds[i].events = POLLIN;
			
		}

	}else
	{
		printf("Usage:%s <dev> <dev>\n",argv[0]);
		return -1;
	}
	


	while (1)
	{
		for (int i = 0; i < nfds; i++)
		{
			fds[i].revents = 0;					//很重要,每次清零
		}

		ret = poll(fds,nfds,timeout_ms);
		if (ret > 0)
		{
			printf("ret = %d"\n,ret);
			for (int i = 0; i < nfds; i++)
			{
				if (fds[i].revents == POLLIN)
				{
					while (read(fds[i].fd, &event, sizeof(event)) == sizeof(event))		//非阻塞模式->查询,会一直读;
					{
						printf("get %s event: event type = -0x%x, event code = 0x%x, event value = 0x%x\n", argv[i+1],event.type,event.code,event.value);
					}
				}
			}

		}else if (ret == 0)
		{
			printf("timeout\n");
		}else
		{
			printf("poll err\n");
		}

	}
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用 `poll` 函数连续监测多个文件描述符的简单示例: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h> #define MAX_EVENTS 2 int main() { struct pollfd fds[MAX_EVENTS]; int timeout = 5000; // 超时时间,单位为毫秒 // 打开两个文件描述符 int fd1 = open("file1.txt", O_RDONLY); int fd2 = open("file2.txt", O_RDONLY); // 设置文件描述符和事件 fds[0].fd = fd1; fds[0].events = POLLIN; fds[1].fd = fd2; fds[1].events = POLLIN; while (1) { int ret = poll(fds, MAX_EVENTS, timeout); if (ret == -1) { perror("poll"); exit(EXIT_FAILURE); } else if (ret == 0) { printf("Timeout occurred.\n"); } else { for (int i = 0; i < MAX_EVENTS; i++) { if (fds[i].revents & POLLIN) { printf("File descriptor %d has data to read.\n", fds[i].fd); char buffer[1024]; ssize_t bytesRead = read(fds[i].fd, buffer, sizeof(buffer)); if (bytesRead == -1) { perror("read"); exit(EXIT_FAILURE); } printf("Read %zd bytes: %s\n", bytesRead, buffer); } } } } // 关闭文件描述符 close(fd1); close(fd2); return 0; } ``` 在上面的示例中,我们使用 `poll` 函数监测两个文件描述符 `fd1` 和 `fd2` 是否有数据可读。首先,我们打开了两个文件描述符并设置对应的事件为 `POLLIN`,然后进入一个无限循环。在循环中,调用 `poll` 函数来等待事件发生,如果有事件发生,则通过检查 `revents` 域来确定是哪个文件描述符上有数据可读。然后,我们使用 `read` 函数从文件中读取数据并进行处理。 这个示例展示了如何使用 `poll` 函数来连续监测多个文件描述符的状态,并在有数据可读时进行相应的处理。需要注意的是,示例中的超时时间设置为 5 秒,可以根据需要进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值