阻塞式按键驱动

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>						/*delay*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>                        	/*kmalloc*/
#include <linux/vmalloc.h>                    	/*vmalloc*/
#include <linux/types.h>                       	/*ssize_t*/
#include <linux/fs.h>                         	/*file_operaiotns*/
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm-generic/ioctl.h>
#include <asm-generic/errno-base.h>


/************硬件相关*************/
#include <mach/iomux-mx6dl.h>	
#define	GPIO_5				IMX_GPIO_NR(1,5)
#define	Key_INT_PIN			GPIO_5
#define Key_INT_Number 		gpio_to_irq(Key_INT_PIN)
#define Falling_Trigger 	"Falling_Trigger\n"

/**主设备号和次设备号**/
#define DEVICE_MAJOR 104
#define DEVICE_MINOR 0


/*在/sys目录创造一个类*/
static struct class *gpio_class;	
/*在这个类下,创造一个设备节点*/
static struct cdev *gpio_class_dev;

static struct timer_list buttons_timer;
//定义并初始化等待队列头部
static DECLARE_WAIT_QUEUE_HEAD(Key_Status_Read_Wait);
static int wait_flag = 0;


/*open函数的实现*/
static int gpio_open(struct inode *inode, struct file *file)
{

	printk(KERN_ALERT"GPIO OPEN\n");
	return 0;

}

/*release函数的实现*/
static int gpio_close(struct inode *inode, struct file *file)
{	
	
	return 0;
}



ssize_t Key_Status_Read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
	printk("\n-->>start to read\n");
	/*******
	唤醒一个被wait_event_interruptible()的进程,需要满足: 
    在 1)condition为真的前提下,2) 调用wake_up()。

  	wait_event_interruptible(wq, condition)  修改当前进程为TASK_INTERRUPTIBLE状态,
  	并把进程添加到等待队列wq中, 意味着该进程要等到被唤醒时才能继续运行,
  	或者被信号打断;如果没有被唤醒或者信号打断,它会一直等下去。  
    
	*******/
	wait_event_interruptible(Key_Status_Read_Wait, wait_flag);
	wait_flag = 0;

	printk("-->>read return\n");
	if (copy_to_user(buf, Falling_Trigger, strlen(Falling_Trigger)))
		return -EFAULT;
	return strlen(Falling_Trigger);
}

/*具体的文件操作集合*/
static const struct file_operations gpio_fops = 
{
	/*这是拥有者*/
	.owner			= THIS_MODULE,
	.open			= gpio_open,
	.release 		= gpio_close,
	.read		 	= Key_Status_Read,
};

static irqreturn_t Deal_With_KEY_INT(int irq, void *dev_id)
{
	printk("-->>interrupt happend!\n");
	//10ms(HZ/100)后启动定时器
	mod_timer(&buttons_timer, jiffies+HZ/5);	
	return IRQ_HANDLED;
}

static void buttons_timer_function(unsigned long data)
{
	printk("-->>buttons_timer_function\n");
	if(gpio_get_value(Key_INT_PIN)==0)
	{
		wait_flag = 1;
		wake_up(&Key_Status_Read_Wait);
	}
}
static void KEY_INT_init(void)
{
	int ret;
	
	printk("irq = %u\n", Key_INT_PIN);
	
	mxc_iomux_v3_setup_pad(MX6DL_PAD_GPIO_5__GPIO_1_5); //configures a single pad in the iomuxer
	ret=gpio_request(Key_INT_PIN, "Key_INT_PIN");
	if(ret==0)
	{
		printk("gpio_request  success\n");
	}
	else
	{
		printk("gpio_request  fail\n");

	}	
	ret=gpio_direction_input(Key_INT_PIN);
	if(ret==0)
	{
		printk("gpio_direction_input  success\n");
	}
	else
	{
		printk("gpio_direction_input  fail\n");

	}	
	ret = request_irq(Key_INT_Number, Deal_With_KEY_INT,\
		 IRQF_TRIGGER_FALLING, "Deal_With_KEY_INT", NULL);//IRQF_TRIGGER_RISING
	if(ret==0)
	{
		printk("request_irq  success=%d\n",Key_INT_Number);
	}
	else
	{
		printk("request_irq  fail=%d-[%d]\n",Key_INT_Number,ret);

	}

}


/*驱动的初始化函数*/
static int gpio_init(void)
{
	/*设备初始化*/
	int devno;
	/*设备号的申请,创建*/
	devno = MKDEV(DEVICE_MAJOR,DEVICE_MINOR);/*静态申请设备号*/	
		
	gpio_class_dev = cdev_alloc();
	
	cdev_init(gpio_class_dev,&gpio_fops);/*字符设备初始化,绑定相关操作到设备*/
	
	gpio_class_dev->owner = THIS_MODULE;/*设备的拥有者*/
	
	cdev_add(gpio_class_dev,devno,1);/*添加设备到内核*/
	
	register_chrdev(DEVICE_MAJOR,"gpios",&gpio_fops);/*注册设备*/	
	
	gpio_class = class_create(THIS_MODULE, "gpios");/*创建设备类,用于自动创建设备文件*/	
	
	device_create(gpio_class,NULL,MKDEV(DEVICE_MAJOR,DEVICE_MINOR),NULL,"gpios");/*依据以前创建的设备类,创建设备*/
	
	KEY_INT_init();

	/*加定时器防抖动*/
	init_timer(&buttons_timer);
	buttons_timer.function = buttons_timer_function;
	add_timer(&buttons_timer);

	return 0;
}

/*退出函数*/
static void gpio_exit(void)
{
	
	free_irq(Key_INT_Number,NULL);
	gpio_free(Key_INT_PIN);
	/*设备卸载*/
	unregister_chrdev(DEVICE_MAJOR,"gpios");								
	device_destroy(gpio_class,MKDEV(DEVICE_MAJOR,DEVICE_MINOR));						
	class_destroy(gpio_class);

	del_timer(&buttons_timer);
}

/*LICENSE信息*/
MODULE_LICENSE("GPL");
/*卸载和加载*/
module_init(gpio_init);
module_exit(gpio_exit);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值