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

📄 键盘驱动程序.c

📁 arm(s3c2410)-linux(2.6.18)环境下的键盘扫描驱动
💻 C
字号:
#include<linux/module.h>
#include<linux/init.h>
#include<linux/config.h>
#include<linux/kernel.h>                  
#include<linux/fs.h>                       
#include<linux/interrupt.h>                 
#include<linux/wait.h>                    
#include<linux/cdev.h>                     
#include<linux/sched.h>                      
#include<linux/devfs_fs_kernel.h>          


#include<asm/hardware.h>                
#include<asm/delay.h>                   
#include<asm/uaccess.h>                  
#include<asm/io.h>                      
#include<asm/arch-s3c2410/regs-gpio.h>     
#include<asm/arch-s3c2410/irqs.h>          


#define     KEY_NUM 4
#define     DEVICE_NAME "key"
#define     KEY_MAJOR 0
#define     KEY_MINOR 0
#define     MAX_KEY_BUF  16


#define     KEY_IRQ1 IRQ_EINT0   
#define     KEY_IRQ2 IRQ_EINT2
#define     KEY_IRQ3 IRQ_EINT11
#define     KEY_IRQ4 IRQ_EINT19

#define     KEY_STATUS_1      0
#define     KEY_STATUS_2      2
#define     KEY_STATUS_3      11
#define     KEY_STATUS_4      19

define     KEY_STATUS_DOWNX    0
#define     KEY_STATUS_DOWN     1 
#define     KEY_STATUS_UP         2


#define     KEY_TIMER_DELAY1   HZ/100   //100ms
#define     KEY_TIMER_DELAY2   HZ/5   //200ms
#define     KEY_TIMER_DELAY3   HZ      //1000ms

//unsigned long    rINTPND;
void __iomem *     rINTPND;
void __iomem *     rINTMASK;
void __iomem *     rEINPEND;
void __iomem *     rEINPMASK;
void __iomem *     rSRCPND;
void __iomem *     rEXTINT0;
void __iomem *     rEXTINT1;
void __iomem *     rEXTINT2;
void __iomem *     rGPFDATA;
void __iomem *     rGPGDATA;
void __iomem *     rGPFCON;
void __iomem *     rGPGCON;

 

#define     INT_IRQ1        1<<0
#define     INT_IRQ2        1<<2
#define     INT_IRQ11       1<<11
#define     INT_IRQ19       1<<19
#define     INT_IRQ8_23     1<<5

 

static int key_major=KEY_MAJOR;

 

static int flag=0;


typedef struct {
        unsigned int keyStatus[KEY_NUM];         
 unsigned char buf[MAX_KEY_BUF];        
      unsigned int head,tail;                      
      wait_queue_head_t wq;                    
   struct cdev  k_dev;
} key_dev;


static struct timer_list key_timer[KEY_NUM];

 

static key_dev * k_dev;  


static struct key_info      
{
    int irq_no;
    unsigned int gpio_port;
    unsigned int gpio_function;
    int  key_no;
} key_info_tab[KEY_NUM]=
{
   { KEY_IRQ1,S3C2410_GPF0,S3C2410_GPF0_EINT0 ,0 } 
   ,
   { KEY_IRQ2,S3C2410_GPF2,S3C2410_GPF2_EINT2,1 } 
   ,
   { KEY_IRQ3,S3C2410_GPG3,S3C2410_GPG3_EINT11,2 } 
   ,
   { KEY_IRQ4,S3C2410_GPG11,S3C2410_GPG11_EINT19 ,3 } 
};

 

static unsigned char key_read(void)
{
   unsigned char  ret;
   ret=k_dev->buf[k_dev->tail];
   k_dev->tail++;
   k_dev->tail=(k_dev->tail)%(MAX_KEY_BUF);
   
   return ret;
}

static void key_write(unsigned char key)
{
   k_dev->buf[k_dev->head]=key;
   k_dev->head++;
   k_dev->head=(k_dev->head)%(MAX_KEY_BUF);
}

static void key_event(int key)
{

    unsigned char key_no='0';
   printk("key_event  key =%d !\n",key);

    if(key==0)
       key_no='a';
    else if(key==1)
       key_no='b';
    else if(key==2)
       key_no='c';
    else if(key==3)
       key_no='d';
    key_write(key_no);
     
    key_num=key;
       flag=1;
    wake_up_interruptible(&(k_dev->wq)); 
   
}

 

static void clear_pending(unsigned int value)
{
   writel(value,rSRCPND);
   writel(value,rINTPND);
}

 


static void clear_sub_pending(unsigned int value)
{
   writel(value,rEINPEND);
   //writel(value,rINTPND);
}

static void clear_interrupt(int key)
{

    unsigned int value;
    value=ioread32(rINTPND);
     
    if(value==INT_IRQ1)
    {
       clear_pending(INT_IRQ1);
    }
    else if(value==INT_IRQ2)
    {
       clear_pending(INT_IRQ1);
    }
    else if(value==INT_IRQ8_23)
    {
        clear_pending(INT_IRQ8_23);
        value=ioread32(rEINPEND);
        if(value==INT_IRQ11)
        {
           clear_sub_pending(INT_IRQ11);
        }
        else if(value==INT_IRQ19)
        {
            clear_sub_pending(INT_IRQ19);
        }
    }

}


static int Is_key_down(int key)
{
   int ret;
 
   int value;
   value=s3c2410_gpio_getpin(key_info_tab[key].gpio_port);
  
  if(value==0)
     ret=1;
  else 
    ret=0;
   return ret;
  
}


static void key_timer_handle(unsigned long arg)
{
    int key=(int)arg;
     if(Is_key_down(key))
    {
         if(k_dev->keyStatus[key]==KEY_STATUS_DOWNX)
        {
            k_dev->keyStatus[key]=KEY_STATUS_DOWN;
            key_timer[key].expires=jiffies+KEY_TIMER_DELAY3;
     key_event(key);
  
        add_timer(&key_timer[key]);  
}
       else
       {
            key_timer[key].expires=jiffies+KEY_TIMER_DELAY2;
     add_timer(&key_timer[key]);  
}
    }
    else
    {
 printk("key %d up!\n",key);
         k_dev->keyStatus[key]=KEY_STATUS_UP;
         enable_irq(key_info_tab[key].irq_no); 

    }
    
}


static irqreturn_t s3c2410_key_ISR(int irq,void *dev_id,struct pt_regs *regs)
{
    int value;
    int key;
    struct key_info * k;

    k=(struct key_info *)dev_id;
    key=k->key_no;

        if(key<0 || key>3 )
    {
        printk("Error irq no!\n");
        return -1;
    }
    disable_irq(key_info_tab[key].irq_no);  //绂佹

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -