|  | 
 
| 硬件平台:TQ2440 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #include
 #define DEVICE_NAME "key-device"
 MODULE_DESCRIPTION("759981398@qq.com");
 MODULE_AUTHOR("traveler");
 MODULE_LICENSE("Dual BSD/GPL");
 //声明一个等待队列
 static DECLARE_WAIT_QUEUE_HEAD(keys_wait_irq) ;
 //事件 用于同步用户与驱动程序之间的数据
 static volatile int key_event = 0;
 //存储按键的值
 static volatile int key_value = 0;
 static void * key_devid = (void *)0;
 //ISR中断服务程序
 static irqreturn_t keys_irq(int irq,void *devid)
 {
 int down ;
 //GPIO的 基址 虚拟地址
 //对 GPIO的所有操作 都以此地址 作为 参考 地址
 const unsigned int gpio_base = (unsigned int )S3C24XX_VA_GPIO;
 //获取 GPFDAT寄存器 的 虚拟地址
 const unsigned int gpfdat = gpio_base + 16 * 5 + 4;
 if(devid!=key_devid)
 {
 printk("<1>DRIVER ERROR !devid=%dn",(int)devid);
 return IRQ_RETVAL(IRQ_NONE);
 }
 //获取按键引脚状态
 down = (*(unsigned int *)gpfdat) ;
 //如果当前值和存储的值不相等 则唤醒等待队列
 // if((down &0x01) != (key_value&0x01))
 {
 key_value = down & 0x01;
 key_event = 1;
 wake_up_interruptible(&keys_wait_irq);
 }
 //返回标志 中断已服务
 return IRQ_RETVAL(IRQ_HANDLED);
 }
 //读取 按键 状态 用户 调用 参数 列表
 static ssize_t key_read(struct file *filp,char __user *buf,
 size_t count,loff_t *loff)
 {
 int err;
 if(!key_event)
 {
 //如果事件未发生并且文件不允许阻塞,那么返回一个错误标识
 if(filp->f_flags & O_NONBLOCK)
 return -EAGAIN ;
 //等待事件
 wait_event_interruptible(keys_wait_irq,key_event);
 }
 //拷贝数据到用户空间
 err = copy_to_user(buf,(void *)(&key_value),min(sizeof(key_value),count));
 //已经读取了数据,重设事件标志
 key_event = 0;
 //返回拷贝到的数据长度
 return err ? -EFAULT : min(sizeof(key_value),count) ;
 };
 static int key_open(struct inode *inode,struct file *filp)
 {
 int err;
 //GPIO的 基址 虚拟地址
 //对 GPIO的所有操作 都以此地址 作为 参考 地址
 const unsigned int gpio_base = (unsigned int )S3C24XX_VA_GPIO;
 //获取 GPFCON的 地址
 const unsigned int gpfcon = gpio_base + 16 * 5;
 //获取 GPFDAT的 地址
 unsigned int gpfup = gpfcon + 2*4;
 //注册irq函数
 err = request_irq(IRQ_EINT0,keys_irq,IRQ_TYPE_EDGE_BOTH,
 "key0",key_devid);
 if(err)
 return -EBUSY;
 //设置事件标志
 key_event = 1;
 //配置 GPF0 端口 为EINT0
 (*(unsigned int *)gpfcon) &= ~(0x03);
 (*(unsigned int *)gpfcon) |= 0x02;
 //禁止 内部 上拉 电阻
 (*(unsigned int *)gpfup) |= 0x01;
 return 0;
 }
 static int key_release(struct inode *inode,struct file *filp)
 {
 //禁止中断
 disable_irq(IRQ_EINT0);
 //释放中断
 free_irq(IRQ_EINT0,key_devid);
 return 0;
 }
 static struct file_operations key_fops =
 {
 .owner= THIS_MODULE,
 .open = key_open,
 .read = key_read,
 .release = key_release,
 };
 static struct miscdevice key_misc=
 {
 .minor = MISC_DYNAMIC_MINOR,
 .name = DEVICE_NAME,
 .fops = &key_fops,
 };
 static int key_init_module(void)
 {
 int ret ;
 //注册 杂项 设备
 ret = misc_register(&key_misc);
 printk("<1>Module key init,major:10,minor:%dn",key_misc.minor );
 return 0;
 }
 static void key_exit_module(void)
 {
 //注销 杂项设备
 misc_deregister(&key_misc);
 printk("<1>Module key exitn" );
 }
 module_init(key_init_module);
 module_exit(key_exit_module);
 
 
 | 
 |