微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 一个相当详细的MINI2440按键驱动详解

一个相当详细的MINI2440按键驱动详解

时间:11-11 来源:互联网 点击:

p,char __user *buff,size_t count,loff_t *offp)
{
unsigned long err; /*copy_to_user()函数的返回值*/

/*如果key_values 数组里没有值,则会此进程会休眠*/
/*一直到中断来临之后,中断服务程序会唤醒此休眠进程从而继续读取值*/
/*key_values数组里有没有值,是靠ev_press标志位来判断的*/
/*有值,就是1,无值,就是0*/

/*进程等待队列的机制,是进程调度的一种方法*/

if(!ev_press) /*标志位为0,即无数据时*/
{
if(filp->f_flags & O_NONBLOCK) /*??*/
return -EAGAIN;
else /*进程休眠,放进button_waitq等待队列*/
/*这里,把ev_press标志位设成了休眠进程的标志位了?*/
/*这是为了便于利用poll_wait函数*/
/*也就是利于select函数*/
wait_event_interruptible(button_waitq,ev_press);
/*在中断处理函数中,此进程会被唤醒*/
/*唤醒前,ev_press 已被置1了*/
/*唤醒后的执行点从这里开始*/
}

/*下面就是标志位为1,即有数据可读的的处理情况*/

/*那就开始往用户空间读数据呗*/

err = copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count));
/*copy_to_user()函数的使用*/

/*对key_values数组清零*/

memset((void *)key_values,0,sizeof(key_values));

/*对标志位置0*/
/*表示读取过了*/

ev_press = 0;

/*对err的处理*/

if(err) /*读取错误*/
return -EFAULT;
else /*读取正确*/
/*则返回读取到的字节数*/
return min(sizeof(key_values),count);
}

/************************mini2440_buttons_poll()***********************/

static unsigned int mini2440_buttons_poll(struct file *file,struct poll_table_struct *wait)
{
unsigned int mask = 0; /* */

/*poll_wait()函数*/
/*会监测进程队列button_waitq里的进程*/
/*例如,如果mini2440_button_read所在的进程的标志位ev_press置为1了*/
/*那么就不会再等待了*/
/*这实质上就是select函数的运行机制*/

poll_wait(file,&button_waitq,wait);

if(ev_press)
mask |= POLLIN | POLLRDNORM; /*??*/

return mask;
}

==================================================================================

下面是测试代码:

/*按键测试程序*/

#include /*标准输入输出头文件*/

#include /*标准库*/

#include /*一些宏的定义在这里*/

#include /*设备的控制*/

#include /*定义了一些类型*/

#include /*状态*/

#include /*文件控制*/

#include /*选择?*/

#include /*时间方面的函数*/

#include /*有关错误方面的宏*/

/*主函数入口*/

int main(void)
{
int i; /*键盘输出时用到的循环变量*/

int buttons_fd; /*buttons设备号*/

int key_value[4]; /*四个按键的取值*/

/*打开键盘设备文件*/

buttons_fd = open("/dev/buttons",0); /*以0方式打开*/

/*打开出错处理*/

if(buttons_fd < 0) /*打开出错就会返回一个负值*/
{
perror("open device buttons"); /*perror函数?*/

exit(1); /*返回1*/
}

/*for无限循环,等待用户输入*/
/*这是很典型的程序执行方式*/

for(;;)
{
fd_set rds; /*fd_set是types.h中定义的类型,实质上是int型*/
/*rds用来存储设备号*/

int ret; /*for循环内定义的局部变量ret*/

FD_ZERO(&rds); /*rds初始化*/
/*FD_ZERO是哪里定义的呢?*/

FD_SET(buttons_fd,&rds); /*将buttons设备号赋给rds*/
/*FD_SET是哪里定义的呢?*/

/*使用系统调用select检查是否能够从/dev/buttons设备读取数据*/
/*select函数是干什么的呢?*/

ret = select(buttons_fd + 1,&rds,NULL,NULL,NULL);
/*返回值ret*/
/*返回值的具体意义是什么呢?*/

/*对ret的处理*/

if(ret < 0) /*当ret小于0*/
{
perror("select");
exit(1);
}

if(ret == 0) /*当ret等于0*/
{
printf("Timeout.\n");
}
else /*能够读到数据*/
if(FD_ISSET(buttons_fd,&rds)) /*??*/
{
/*读取键盘驱动发出的数据*/
/*key_value和键盘驱动中定义一致*/

int ret = read(buttons_fd,key_value,sizeof(key_value)); /*注意此处的ret和前面的ret有何不同*/
/*注意键盘设备读取的特点*/

/*对ret的处理*/
if(ret != sizeof(key_value)) /*没有接收够*/
{
if(errno != EAGAIN) /*???*/
perror("read buttons\n");
continue;
}
else /*正确接收,则打印到标准终端*/
{
for(i = 0;i < 4;i++) /*最开始定义的循环变量i*/
printf("K%d %s, key value = 0x%02x\n",i,(key_value[i] & 0x80) ? "released" : key_value[i] ? "pressed down" : "",key_value[i]);
/*这一连串的输出,要注意格式*/
}
}
}

/*关闭设备*/

close(buttons_fd);

return 0; /*主函数返回*/

END!!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top