Chinaunix首页 | 论坛 | 博客
  • 博客访问: 119386
  • 博文数量: 24
  • 博客积分: 616
  • 博客等级: 中士
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-01 10:54
文章分类
文章存档

2012年(24)

我的朋友

分类: LINUX

2012-06-27 10:46:12

/***********************************************************
**                 按键中断驱动程序                       **
***********************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define DEVICE_NAME   "keys_eint" //设备文件名
//定义中断使用的结构体 
//1.定义外部中断所用的中断号
//2.定义外部中断所对应的GPIO端口
//3.定义键值
//4.定义每个按键的名字
static struct irq_table_data{
     int irq;
     int pin;
     int button_number;
     char * button_name; 
};
//结构体实体定义
static struct irq_table_data button_irqs[]={
     {IRQ_EINT11,S3C2410_GPG(3),0,"KEY1"},
     {IRQ_EINT13,S3C2410_GPG(5),1,"KEY2"},
     {IRQ_EINT14,S3C2410_GPG(6),2,"KEY3"},
     {IRQ_EINT15,S3C2410_GPG(7),3,"KEY4"},
};
//定义按键状态变量
static volatile char key_values[]={'0','0','0','0'};
//创建等待队列
static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue);
//定义中断信息标志
static volatile unsigned int flag_irq=0;
static irqreturn_t button_irq_handler(int irq,void * dev_id)
{
      struct irq_table_data *button_irqs=(struct irq_table_data*)dev_id;
      int down;
      down=!s3c2410_gpio_getpin(button_irqs->pin);
      if(down!=(key_values[button_irqs->button_number]&1))
      {
         key_values[button_irqs->button_number]='0'+down;
         flag_irq=1;
         wake_up_interruptible(&button_wait_queue);
      }
      return IRQ_RETVAL(IRQ_HANDLED);
}
//打开文件注册中断,如果失败则返回退出
static int button_open(struct inode *inode,struct file *file)
{
 int ret=0;
 unsigned int i;
  for(i=0;i<4;i++)
  {
        ret=request_irq(button_irqs[i].irq, button_irq_handler, IRQ_TYPE_EDGE_BOTH, button_irqs[i].button_name, (void *)&button_irqs[i]);
        if(ret)
        {
            break; 
        }
  }
  if(ret)
  {
      i--;
      for(;i>=0;i--)
      {
           disable_irq(button_irqs[i].irq);
           free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
          
       }
       return -EBUSY;
  }
  else
  {
       flag_irq=1;
       return 0;
  }
}
static int button_close(struct inode *inode,struct file *file)
{
    int i;
    for(i=0;i<4;i++)
    {
          free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);
     }
     return 0;
}
static int button_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
      unsigned long err;
      if(flag_irq==0)
      {
            if(filp->f_flags&O_NONBLOCK)//f_flags为unsigned int类型    当中断标示为0并且以非阻塞方式打开时
                return -EAGAIN;
            else
                wait_event_interruptible(button_wait_queue,flag_irq);//否则就在这里阻塞掉
      } 
      flag_irq=0;
      err=copy_to_user(buff,(const void*)key_values,min(sizeof(key_values),count));
      return err ? -EFAULT:min(sizeof(key_values),count);
}
static unsigned int button_poll(struct file *file,struct poll_table_struct *wait)
{
       unsigned int mask=0;
       poll_wait(file,&button_wait_queue,wait);
       if(flag_irq)
       {
             mask=POLLIN|POLLRDNORM;
        } 
        return mask;
}
 
 
 
 
static struct file_operations dev_fops={
 .owner=THIS_MODULE,
 .open=button_open,
 .release=button_close,
 .read=button_read,
 .poll=button_poll,
};
static struct miscdevice misc={
 .name=DEVICE_NAME,
 .minor=MISC_DYNAMIC_MINOR,
 .fops=&dev_fops,
};
static int __init dev_init(void)
{
 //主要工作是注册模块为混杂设备
 int ret;
 ret=misc_register(&misc);
 return ret;
}
static void __exit dev_exit(void)
{
  misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("friendly_arm");
阅读(1384) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~