[cpp] view plaincopy
 
  1. #include <linux/kernel.h>  
  2.  #include <linux/module.h>  
  3.  #include <linux/init.h>  
  4.  #include <linux/fs.h>  
  5.  #include <linux/gpio.h>  
  6.  #include <linux/types.h>  
  7.  #include <linux/cdev.h>  
  8.  #include <linux/interrupt.h>  
  9.  #include <linux/sched.h>  
  10.  #include <linux/device.h>  
  11.  #include <linux/poll.h>  
  12.  #include <linux/semaphore.h>  
  13.  #include <linux/timer.h>  
  14.   
  15.  #include <asm/irq.h>  
  16.  #include <asm/uaccess.h>  
  17.   
  18.  //#include <mach/hardware.h>  
  19.  #include <mach/irqs.h>  
  20.   
  21.   
  22.  #define DEVICE_NAME "keyint"  
  23.  #define KEYNUM 6  
  24.  dev_t devid;  
  25.   
  26.  //static DEFINE_SEMAPHORE(key_lock);  //declare a mutex lock for keyint  
  27.    //定义一个信号量  
  28.  struct semaphore key_lock;  
  29.  static struct fasync_struct *key_async;  
  30.  static struct timer_list key_timer;  
  31.   
  32.  struct key_irq_desc {  
  33.      int irq;        //irq num  
  34.      unsigned long flags;    //irq flags,identified the way of irq here,eq.edge,level  
  35.      char *name;        //irq name  
  36.  };  
  37.   
  38.  static struct key_irq_desc key_irqs[] = {  
  39.      //下降沿产生中断  
  40.      {IRQ_EINT(0), IRQF_TRIGGER_FALLING, "KEY1"},  
  41.      {IRQ_EINT(1), IRQF_TRIGGER_FALLING, "KEY2"},  
  42.      {IRQ_EINT(2), IRQF_TRIGGER_FALLING, "KEY3"},  
  43.      {IRQ_EINT(3), IRQF_TRIGGER_FALLING, "KEY4"},  
  44.      {IRQ_EINT(4), IRQF_TRIGGER_FALLING, "KEY5"},  
  45.      {IRQ_EINT(5), IRQF_TRIGGER_FALLING, "KEY6"},  
  46.  };  
  47.   
  48.  /*define a waiting queue here*/  
  49.  static DECLARE_WAIT_QUEUE_HEAD(key_waitq);  
  50.   
  51.  /*define a event flag ev_press*/  
  52.  static volatile int ev_press = 0;  
  53.   
  54.  static volatile int press_cnt[KEYNUM] = {0,0,0,0,0,0};  
  55.   
  56.   
  57.   
  58.   
  59.  /*中断处理函数*/  
  60.  static irqreturn_t keys_interrupt(int irq, void *dev_id)  
  61.  {  
  62.      volatile int *press_cnt = (volatile int *) dev_id;  
  63.         /*set the pressed key flag(must do here due to not be static value)*/  
  64.      *press_cnt = *press_cnt + 1;  
  65.   
  66.      //延时10ms后执行定时器处理函数  
  67.      mod_timer(&key_timer,jiffies+HZ/100);        //start timer after 10ms  
  68.   
  69.      return IRQ_RETVAL(IRQ_HANDLED);  
  70.  }  
  71.   
  72.   
  73. //定时器处理函数  
  74.  static void key_timer_func(unsigned long data)  
  75.  {  
  76.            
  77.      ev_press = 1;  
  78.      //唤醒等待队列  
  79.      wake_up_interruptible(&key_waitq);  
  80.      kill_fasync(&key_async, SIGIO, POLL_IN);  
  81.  }  
  82.   
  83.   
  84.  static int key_fasync(int fd, struct file *filp, int on)  
  85.  {  
  86.      printk("Function key_fasync\n");  
  87.      return fasync_helper(fd,filp,on,&key_async);  
  88.  }  
  89.   
  90.   
  91.   
  92.  static unsigned key_poll(struct file *file, poll_table *wait)  
  93.  {  
  94.      unsigned int mask=0;  
  95.      //指明要使用的等待队列  
  96.      poll_wait(file,&key_waitq,wait);  
  97.   
  98.   
  99.     //返回掩码  
  100.      if(ev_press)  
  101.      mask |= POLL_IN | POLLRDNORM;  
  102.   
  103.      printk("poll wait\n");  
  104.   
  105.      return mask;  
  106.  }  
  107.   
  108.  static int key_open(struct inode *inode, struct file *file)  
  109.  {  
  110.      int num;  
  111.   
  112.      if(file->f_flags & O_NONBLOCK) {  
  113.        if(down_trylock(&key_lock)) return -EBUSY;  
  114.      }  
  115.   
  116.      else {  
  117.        down(&key_lock);  
  118.      }  
  119.        
  120.      //为每个按键注册中断处理程序  
  121.      for(num=0;num<KEYNUM;num++) {  
  122.        request_irq(key_irqs[num].irq, keys_interrupt, key_irqs[num].flags, key_irqs[num].name, (void *)&press_cnt[num]);  
  123.      }  
  124.   
  125.   
  126.      return 0;  
  127.  }  
  128.   
  129.  static int key_close(struct inode *inode, struct file *file)  
  130.  {  
  131.      int num;  
  132.      //释放中断号  
  133.      for(num=0;num<6;num++) {  
  134.        free_irq(key_irqs[num].irq, (void *)&press_cnt[num]);  
  135.      }  
  136.      up(&key_lock);  
  137.   
  138.      printk("key_close free irqs\n");  
  139.   
  140.      return 0;  
  141.  }  
  142.   
  143.  static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)  
  144.  {  
  145.  //    unsigned int err;  
  146.        
  147.      //判断是阻塞读还是非阻塞读  
  148.      if(filp->f_flags & O_NONBLOCK) {  
  149.        if(!ev_press)  return -EAGAIN;  
  150.      }  
  151.   
  152.      else {  
  153.        /*if ev_press==0,then sleep*/  
  154.        /*阻塞,当有按键按下时(中断)被唤醒*/  
  155.        wait_event_interruptible(key_waitq,ev_press);  
  156.      }  
  157.      //阻塞结束,有键按下了  
  158.   
  159.      ev_press = 0;  
  160.   
  161.      //拷贝数据到用户空间  
  162.      copy_to_user(buff,(const void *)press_cnt,min(sizeof(press_cnt),count));  
  163.      memset((void *)press_cnt,0,sizeof(press_cnt));  
  164.   
  165.  //    printk("read and clean press_cnt\n");  
  166.   
  167.      return 1;  
  168.  }  
  169.   
  170.  static struct file_operations key_ops = {  
  171.      .owner     = THIS_MODULE,  
  172.      .open     = key_open,  
  173.      .release = key_close,  
  174.      .read     = key_read,  
  175.      .poll     = key_poll,  
  176.      .fasync     = key_fasync,  
  177.  };  
  178.   
  179.  static struct cdev *cdev_keyint;  
  180.  static struct class *keyint_class;  
  181.   
  182.   
  183.   
  184.  //模块初始化函数  
  185.  static int __init s3c6410_keyint_init(void) {  
  186.      int val;  
  187.        
  188.      /*timer initial */  
  189.      init_timer(&key_timer);  
  190.      key_timer.function = key_timer_func;  
  191.      add_timer(&key_timer);  
  192.   
  193.          /*初始化信号量*/  
  194.         init_MUTEX(&key_lock);  
  195.      /*register device*/  
  196.      val = alloc_chrdev_region(&devid,0,1,DEVICE_NAME);  
  197.      if(val) {  
  198.        return -1;  
  199.        printk("register keyint error\n");  
  200.      }  
  201.   
  202.      cdev_keyint = cdev_alloc();  
  203.      cdev_init(cdev_keyint, &key_ops);  
  204.      cdev_keyint->owner = THIS_MODULE;  
  205.      cdev_keyint->ops   = &key_ops;  
  206.        
  207.      val = cdev_add(cdev_keyint,devid,1);  
  208.      if(val) {  
  209.        return -1;  
  210.        printk("add device error\n");  
  211.      }  
  212.   
  213.      keyint_class = class_create(THIS_MODULE,DEVICE_NAME);  
  214.      device_create(keyint_class,NULL,devid,NULL,"%s",DEVICE_NAME);  
  215.        
  216.      printk("KEY initialezed ^_^\n");  
  217.      return 0;  
  218.  }  
  219.   
  220.  static void __exit s3c6410_keyint_exit(void)  
  221.  {  
  222.       cdev_del(cdev_keyint);  
  223.      device_destroy(keyint_class,devid);  
  224.      class_destroy(keyint_class);  
  225.      unregister_chrdev_region(devid,1);  
  226.  }  
  227.   
  228.   
  229.  module_init(s3c6410_keyint_init);  
  230.  module_exit(s3c6410_keyint_exit);  
  231.   
  232.  MODULE_LICENSE("GPL");  


 

 

测试程序:

[cpp] view plaincopy
 
  1. #include <stdio.h>  
  2.  #include <stdlib.h>  
  3.  #include <unistd.h>  
  4.  #include <sys/ioctl.h>  
  5.   
  6.  int main(int argc, char **argv)  
  7.  {  
  8.      int fd;  
  9.      int val;  
  10.      int i;  
  11.      int key_value[6];  
  12.             
  13.      fd = open("/dev/keyint",0);  
  14.      if(fd<0) {  
  15.        printf("open devie error\n");  
  16.        return -1;  
  17.      }  
  18.   
  19.      while(1) {  
  20.        val = read(fd,key_value, sizeof(key_value));  
  21.        if(val<0) {  
  22.          printf("read error\n");  
  23.          continue;  
  24.        }  
  25.   
  26.        for(i=0;i<6;i++) {  
  27.           if(key_value[i])  
  28.           printf("KEY%d pressed\n",(i+1),key_value[i]);  
  29.            
  30.        }    
  31.          
  32.      }  
  33.      close(fd);  
  34.      return 0;  
  35.   
  36.  }  


 

 

测试现象