代码如下:
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
static struct input_dev *button_dev;
#define BUTTON_IRQ IRQ_EINT2
static struct timer_list buttons_timer; /* 定义一个定时器结构体 */
static void func(void)
{
int flag;
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0));
flag = gpio_get_value(S5PV210_GPH0(2));
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f));
input_report_key(button_dev, KEY_LEFT, !flag);
input_sync(button_dev);
}
//定义tasklet并绑定tasklet调度函数
DECLARE_TASKLET(mytasklet, func, 0);
//DECLARE_WORK(mywork, func);
static void buttons_timer_function(unsigned long data)
{
tasklet_schedule(&mytasklet); //在上半步中进行tasklet调度
//schedule_work(&mywork);
}
//中断的上半步
static irqreturn_t button_interrupt(int irq, void *dummy)
{
/* 修改定时器定时时间,定时10ms,即10秒后启动定时器
* HZ 表示100个jiffies,jiffies的单位为10ms,即HZ = 100*10ms = 1s
* 这里HZ/100即定时10ms
*/
mod_timer(&buttons_timer, jiffies + (HZ /100));
return IRQ_HANDLED;
}
static int __init s5pv210_button_init(void)
{
int error;
//add a timer to debouncing
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
error = gpio_request(S5PV210_GPH0(2), "gph0_2");
if (error)
{
printk(KERN_INFO "gpio_request fail\n");
}
//set to the eint2 mode
s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f));
if (request_irq(BUTTON_IRQ, button_interrupt, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button-sw5", NULL))
{
printk(KERN_ERR "button.c: Can't allocate irq %d\n", BUTTON_IRQ);
return -EBUSY;
}
button_dev = input_allocate_device();
if (!button_dev) {
printk(KERN_ERR "button.c: Not enough memory\n");
error = -ENOMEM;
goto err_free_irq;
}
button_dev->evbit[0] = BIT_MASK(EV_KEY);
button_dev->keybit[BIT_WORD(KEY_LEFT)] = BIT_MASK(KEY_LEFT);
error = input_register_device(button_dev);
if (error) {
printk(KERN_ERR "button.c: Failed to register device\n");
goto err_free_dev;
}
return 0;
err_free_dev:
input_free_device(button_dev);
err_free_irq:
free_irq(BUTTON_IRQ, button_interrupt);
return error;
}
static void __exit s5pv210_button_exit(void)
{
input_unregister_device(button_dev);
free_irq(BUTTON_IRQ, button_interrupt);
}
module_init(s5pv210_button_init);
module_exit(s5pv210_button_exit);
// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("Mark <867439374@qq.com>"); // 描述模块的作者
MODULE_DESCRIPTION("s5pv210 button driver"); // 描述模块的介绍信息
MODULE_ALIAS("s5pv210_button"); // 描述模块的别名信息