📄 button.c
字号:
#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <asm/hardware.h>#include <asm/delay.h>#include <asm/uaccess.h>#include <asm-arm/arch-s3c2410/regs-gpio.h>#include <asm/io.h>#include <asm-arm/arch-s3c2410/irqs.h>#include <asm-arm/irq.h>#include <linux/interrupt.h>#include <linux/wait.h>#define BUTTON_IRQ1 IRQ_EINT5#define BUTTON_IRQ2 IRQ_EINT6#define DEVICE_NAME "button"static int buttonMajor=0;#define BUTTONMINOR 0#define MAX_BUTTON_BUF 16 #define BUTTONSTATUS_1 5#define BUTTONSTATUS_2 6static 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 ret=%d\n",ret); 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,};static int __init s3c2410_button_init(void){ int ret; set_irq_type(BUTTON_IRQ1,IRQT_FALLING); set_irq_type(BUTTON_IRQ2,IRQT_FALLING); buttonEvent=buttonEvent_dummy; ret=register_chrdev(0,DEVICE_NAME,&button_fops); if(ret<0) { printk("button: can't get major number\n"); return ret; } buttonMajor=ret;#ifdef CONFIG_DEVFS_FSdevfs_mk_cdev(MKDEV(buttonMajor,BUTTONMINOR),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);#endif //buttondev.head=buttondev.tail=0; buttondev.buttonStatus=BUTTONSTATUS_1; init_waitqueue_head(&(buttondev.wq)); printk(DEVICE_NAME" initialized\n"); return 0;}static unsigned char buttonRead(void){ unsigned char button_ret; button_ret=BUF_TAIL; buttondev.tail=INCBUF(buttondev.tail,MAX_BUTTON_BUF); return button_ret;} static void __exit s3c2410_button_eixt(void){#ifdef CONFIG_DEVFS_FS devfs_remove(DEVICE_NAME); #endif unregister_chrdev(buttonMajor,DEVICE_NAME); printk("\nbutton remove\n");}MODULE_LICENSE("GPL");MODULE_AUTHOR("Kision");MODULE_DESCRIPTION ("the first char device driver");module_init(s3c2410_button_init);module_exit(s3c2410_button_eixt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -