[韦东山]嵌入式Linux应用开发 lecture8 读取输入数据

查询方式

        调用open函数时,传入“O_NONBLOCK”参数;

        调用read函数时,若驱动程序中有数据,则read函数返回数据;否则返回错误;

休眠-唤醒方式

        调用open函数时,不要传入“O_NONBLOCK”参数;

        调用read函数时,若驱动程序中有数据,则read函数返回数据;否则在内核态中休眠;

                                     当出现数据时,驱动程序会将APP唤醒,read函数恢复执行并将数据返回;

#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()头文件
#include <string.h>           //strcmp()头文件
#include <unistd.h>           //read()头文件

 
/* input:./01_get_input_info /dev/input/event0 nonblock*/
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];
    struct input_event event;
	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> [nonblock]\n", argv[0]);  //< >代表必选项 [ ]代表可省略项 
		return -1;
	}

    if (argc == 3 && !(strcmp(argv[2], "nonblock")))
    {
	    fd = open(argv[1], O_RDWR | O_NONBLOCK);    //O_NONBLOCK 查询方式
    }
    else
    {
        fd = open(argv[1], 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");
	}

    while(1)
    {
        len = read(fd, &event, sizeof(event));
        if(len == sizeof(event))
        {
            print("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value)
        }
        else
        {
            print("read err %d\n", len);
        }
    }
 
	return 0;
}

在lecture7的代码基础上进行修改,加入可选项“nonblock”

若输入中含“nonblock”,则以查询(非阻塞)方式读取驱动程序中的数据,返回数据或“read err”;

若输入中不含“nonblock”,则以休眠-唤醒(阻塞)方式读取驱动程序中的数据,返回数据或进入休眠等待数据;

POLL/SELECT方式

(POLL和SELECT的机制一致,但APP接口函数不同)

#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()头文件
#include <string.h>           //strcmp()头文件
#include <unistd.h>           //read()头文件
#include <poll.h>             //poll()头文件

 
/* input:./01_get_input_info /dev/input/event0 */
int main(int argc, char **argv)
{
	int fd;
	int err;
	int len;
    int ret;
	int i;
	unsigned char byte;
	int bit;
	struct input_id id;
	unsigned int evbit[2];
    struct input_event event;
    struct pollfd fds[1];
    nfds_t nfds = 1;

	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>[nonblock]\n", argv[0]);   
		return -1;
	}

	fd = open(argv[1], O_RDWR | O_NONBLOCK);    

	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");
	}

    while(1)
    {
        fds[0].fd = fd;
        fds[0].event = POLLIN;
        fds[0].revents = 0;
        ret = poll(fds, nfds, 5000);
        if(ret > 0)
        {
            if(fds[0].revents == POLLIN)
            {
                while(read(fd, &event, sizeof(event) == sizeof(event))
                {
                    print("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value)
                }
            }
        }
        else if(ret == 0)
        {
            print("time out\n");
        }
        else
        {
            print("poll err \n");
        }
    }
 
	return 0;
}

异步通知方式

流程:注册信号处理函数--打开驱动程序--把APP的进程号告诉驱动程序--使能"异步通知”

#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()头文件
#include <string.h>           //strcmp()头文件
#include <unistd.h>           //read()头文件
#include <signal.h>           //signal()头文件
#include <sys/types.h>        //getpid()头文件
#include <unistd.h>           //getpid()头文件 sleep()头文件

int fd;

void my_sig_handler(int sig)
{
    struct input_event event;
    while(read(fd, &event, sizeof(event)) == sizeof(event))
    {
        print("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value)
    }
}

 
/* input:./05_input_read_faycn /dev/input/event0 */
int main(int argc, char **argv)
{
	int err;
	int len;
    int ret;
	int i;
	unsigned char byte;
	int bit;
	struct input_id id;
	unsigned int evbit[2];
    unsigned int flags;
    int count = 0;

	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>[nonblock]\n", argv[0]);   
		return -1;
	}
    /*注册信号处理函数*/
    signal(SIGIO, my_sig_handler)

    /*打开驱动程序*/
    fd = open(argv[1], O_RDWR | O_NONBLOCK);    
	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");
	}

    /*把APP的进程号告诉驱动程序*/
    fcntl(fd, F_SETOWN, getpid());

    /*使能"异步通知”*/
    flags = fcntl(fd, F_GETFL)
    fcntl(fd, F_SETFL, flags | FASYNC);

    while(1)
    {
        print("main loop count = %d\n", count++);
        sleep(2);        //间隔2s
    }
 
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值