⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key_drv.c

📁 Linux环境下自定义的按键驱动
💻 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 + -