📄 key_drv.c
字号:
/**********************start*******************************/
#i nclude <linux/config.h>
#i nclude <linux/module.h>
#i nclude <linux/version.h>
#i nclude <linux/kernel.h>
#i nclude <linux/init.h>
#i nclude <linux/fs.h>
#i nclude <asm/hardware.h>
#i nclude <asm/delay.h>
#i nclude <asm/uaccess.h>
#i nclude <asm-arm/arch-s3c2410/regs-gpio.h>
#i nclude <asm/io.h>
#i nclude <asm-arm/arch-s3c2410/irqs.h>
#i nclude <asm-arm/irq.h>
#i nclude <linux/interrupt.h>
#i nclude <linux/wait.h>
#define BUTTON_IRQ1 IRQ_EINT16
#define BUTTON_IRQ2 IRQ_EINT17
#define DEVICE_NAME "button"
static int buttonMajor=0;
#define BUTTONMINOR 0
#define MAX_BUTTON_BUF 16
#define BUTTONSTATUS_1 16
#define BUTTONSTATUS_2 17
static unsigned char buttonRead(void);
static int flag=0;
typedef struct {
unsigned int buttonStatus; //按键状态
unsigned char buf[MAX_BUTTON_BUF]; //按键缓冲区
unsigned int head,tail; //按键缓冲区头和尾
wait_queue_head_t wq; //等待队列
} BUTTON_DEV;
static BUTTON_DEV buttondev;
#define BUF_HEAD (buttondev.buf[buttondev.head]) //缓冲区头
#define BUF_TAIL (buttondev.buf[buttondev.tail]) //缓冲区尾
#define INCBUF(x,mod) ((++(x)) & ((mod)-1)) //移动缓冲区指针
static void (*buttonEvent)(void);
static void buttonEvent_dummy(void) {}
static void buttonEvent_1(void)
{
if(buttondev.buttonStatus==BUTTONSTATUS_2) {
BUF_HEAD=BUTTONSTATUS_2;
}
else {
BUF_HEAD=BUTTONSTATUS_1;
}
buttondev.head=INCBUF(buttondev.head,MAX_BUTTON_BUF);
flag=1;
wake_up_interruptible(&(buttondev.wq));
printk("buttonEvent_1\n");
}
static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)
{
printk("Occured key board Inetrrupt,irq=%d\n",irq-44);
switch (irq) {
case BUTTON_IRQ1:buttondev.buttonStatus=BUTTONSTATUS_1;
break;
case BUTTON_IRQ2:buttondev.buttonStatus=BUTTONSTATUS_2;
break;
default:break;
}
buttonEvent();
return 0;
}
static int button_open(struct inode *inode,struct file *filp)
{
int ret;
buttondev.head=buttondev.tail=0;
buttonEvent=buttonEvent_1;
ret=request_irq(BUTTON_IRQ1,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ1: could not register interrupt\n");
return ret;
}
ret=request_irq(BUTTON_IRQ2,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);
if(ret) {
printk("BUTTON_IRQ2: could not register interrupt\n");
return ret;
}
return 0;
}
static int button_release(struct inode *inode,struct file *filp)
{
buttonEvent=buttonEvent_dummy;
free_irq(BUTTON_IRQ1,NULL);
free_irq(BUTTON_IRQ2,NULL);
return 0;
}
static ssize_t button_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
{
static unsigned char button_ret;
retry:
printk("retry start\n");
if(buttondev.head!=buttondev.tail) {
button_ret=buttonRead();
copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char));
printk("the button_ret is 0x%x\n",button_ret);
return sizeof(unsigned char);
}
else {
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
printk("sleep\n");
//interruptible_sleep_on(&(buttondev.wq));//为安全起见,最好不要调用该睡眠函数
wait_event_interruptible(buttondev.wq,flag);
flag=0;
printk("sleep_after\n");
if(signal_pending(current))
{
printk("rturn -ERESTARTSYS\n");
return -ERESTARTSYS;
}
goto retry;
}
return sizeof(unsigned char);
}
static struct file_operations button_fops= {
.owner = THIS_MODULE,
.open = button_open,
.read = button_read,
.release = button_release,
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -