button按键驱动,相对于前面的LED驱动来说。增加了中断处理以及阻塞与非阻塞方式等新知识点。
先上学习的驱动代码。
内核:linux3.0
板子:fl2440
本文允许转载,但请注明出处:http://blog.csdn.net/u010944778/article/details/45113687
/*********************************************************************************
* Copyright: (C) 2011 Guo Wenxue<guowenxue@gmail.com>
* All rights reserved.
*
* Filename: plat_button.c
* Description: This is the common button driver runs on S3C2440
*
* Version: 1.0.0(10/27/2011~)
* Author: Guo Wenxue <guowenxue@gmail.com>
* ChangeLog: 1, Release initial version on "10/27/2011 11:39:10 AM"
*
********************************************************************************/
#include "s3c_driver.h"
#define DRV_AUTHOR "Guo Wenxue <guowenxue@gmail.com>"
#define DRV_DESC "S3C24XX button driver"
/* Driver version*/
#define DRV_MAJOR_VER 1
#define DRV_MINOR_VER 0
#define DRV_REVER_VER 0
#define DEV_NAME DEV_BUTTON_NAME
//#define DEV_MAJOR DEV_BUTTON_MAJOR
#ifndef DEV_MAJOR
#define DEV_MAJOR 0 /* dynamic major by default */
#endif
#define BUTTON_UP 0 /* Button status is up */
#define BUTTON_DOWN 1 /* Button status is pushed down */
#define BUTTON_UNCERTAIN 2 /* Button status uncerntain */
#define TIMER_DELAY_DOWN (HZ/50) /*Remove button push down dithering timer delay 20ms */
#define TIMER_DELAY_UP (HZ/10) /*Remove button up dithering timer delay 100ms */
static int debug = DISABLE;
static int dev_major = DEV_MAJOR;
static int dev_minor = 0;
/*============================ Platform Device part ===============================*/
/* Button hardware informtation structure*/
struct s3c_button_info
{
unsigned char num; /*Button nubmer 按键号*/
char * name; /*Button nubmer 按键名*/
int nIRQ; /*Button IRQ number 中断号*/
unsigned int setting; /*Button IRQ Pin Setting 中断引脚配置*/
unsigned int gpio; /*Button GPIO port 对应的IO引脚*/
};
/* The button plaotform device private data structure */
struct s3c_button_platform_data //按键数据结构体
{
struct s3c_button_info *buttons; //用来访问按键硬件信息的指针
int nbuttons;//按键数量
};
/* Button hardware informtation data*/ //具体的相应按键信息
static struct s3c_button_info s3c_buttons[] = {
[0] = {
.num = 1,
.name = "KEY1",
.nIRQ = IRQ_EINT0,//中断号
.gpio = S3C2410_GPF(0),
.setting = S3C2410_GPF0_EINT0,//datasheet手册上对应的IO中断口
},
[1] = {
.num = 2,
.name = "KEY2",
.nIRQ = IRQ_EINT2,
.gpio = S3C2410_GPF(2),
.setting = S3C2410_GPF2_EINT2,
},
[2] = {
.num = 3,
.name = "KEY3",
.nIRQ = IRQ_EINT3,
.gpio = S3C2410_GPF(3),
.setting = S3C2410_GPF3_EINT3,
},
[3] = {
.num = 4,
.name = "KEY4",
.nIRQ = IRQ_EINT4,
.gpio = S3C2410_GPF(4),
.setting = S3C2410_GPF4_EINT4,
},
};
/* The button platform device private data */
static struct s3c_button_platform_data s3c_button_data = {
.buttons = s3c_buttons,
.nbuttons = ARRAY_SIZE(s3c_buttons),
};
struct button_device
{
unsigned char *status; /* The buttons Push down or up status */
struct s3c_button_platform_data *data; /* The buttons hardware information data */
struct timer_list *timers; /* The buttons remove dithering timers */
wait_queue_head_t waitq; /* Wait queue for poll() */
volatile int ev_press; /* Button pressed event */
struct cdev cdev;
struct class *dev_class;
} button_device;
static void platform_button_release(struct device * dev)
{
return;
}
static struct platform_device s3c_button_device = {
.name = "s3c_button",
.id = 1,
.dev =
{
.platform_data = &s3c_button_data,
.release = platform_button_release,
},
};
static irqreturn_t s3c_button_intterupt(int irq,void *de_id) //按键中断服务程序
{
int i;
int found = 0;
struct s3c_button_platform_data *pdata = button_device.data;
for(i=0; i<pdata->nbuttons; i++)
{
if(irq == pdata->buttons[i].nIRQ)//找到具体的中断号
{
found = 1;
break;
}
}
if(!found) /* An ERROR interrupt */
return IRQ_NONE;
/* Onl