Mini2440 按键驱动程序学习笔记(一)

2014-11-24 09:19:51 · 作者: · 浏览: 0

按照习惯,先看原理,对所学习的知识结构有了大致的了解了开始阅读别人的代码,仔细分析代码实现的每个过程。由于时间有限,我只了解了一些概念性的理论和内核代码中部分数据结构,学习的过程还有待深入。对于我这样的初学者来说,想把资料中所介绍的每个原理和具体的实现方法都完全掌握,恐怕不止是时间的问题,我所追求的是一种快速上手的方法,先学会用再深入学习。


下面是经我改动后的按键驱动程序:


/*buttons_driver.c*/



#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include


#include



#define DEVICE_NAME "buttons"



struct button_irq_desc {


int irq;


int pin;


int pin_setting;


int number;


char *name;


};



static struct button_irq_desc button_irqs [] = {


{IRQ_EINT8 , S3C2410_GPG0 , S3C2410_GPG0_EINT8 , 0, "KEY0"},


{IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , 1, "KEY1"},


{IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , 2, "KEY2"},


{IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , 3, "KEY3"},


{IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , 4, "KEY4"},


{IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY5"},


};



static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};



static DECLARE_WAIT_QUEUE_HEAD(button_waitq);



static volatile int ev_press = 0;




static irqreturn_t buttons_interrupt(int irq, void *dev_id)


{


struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;



if ('0'== key_values[button_irqs->number]) { // Changed



key_values[button_irqs->number] = '1';


}


else if('1' == key_values[button_irqs->number]){


key_values[button_irqs->number] = '0';


}


ev_press = 1;


wake_up_interruptible(&button_waitq);



return IRQ_RETVAL(IRQ_HANDLED);


}




static int s3c24xx_buttons_open(struct inode *inode, struct file *file)


{


int i;


int err;


//set the interrupt to falling


//友善的是上升沿和下降沿都中断,这里改成下降沿中断


for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {


err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_FALLING,


button_irqs[i].name, (void *)&button_irqs[i]);


if (err)


break;


}



if (err) {


i--;


for (; i >= 0; i--) {


disable_irq(button_irqs[i].irq);


free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);


}


return -EBUSY;


}



ev_press = 1;



return 0;


}




static int s3c24xx_buttons_close(struct inode *inode, struct file *file)


{


int i;



for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {


free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);


}



return 0;


}




static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)


{


unsigned long err;



if (!ev_press) {


if (filp->f_flags & O_NONBLOCK)


return -EAGAIN;