基于Linux内核的input子系统驱动

时间:2022-07-13 17:53:54
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>


#include <asm/gpio.h>
#include <plat/gpio-cfg.h>


/*1.硬件私有结构体*/
struct button_resource {
unsigned long gpio;
int irq;
char *name;
int code;
};


//初始化按键信息
static struct button_resource btn_info[] = {
[0] = {
.gpio = S5PV210_GPH0(0),
.irq = IRQ_EINT(0),
.name = "KEY_L",
.code = KEY_L
},
[1] = {
.gpio = S5PV210_GPH0(1),
.irq = IRQ_EINT(1),
.name = "KEY_S",
.code = KEY_S
},

[2] = {
.gpio = S5PV210_GPH0(2),
.irq = IRQ_EINT(2),
.name = "KEY_ENTER",
.code = KEY_ENTER
},
};


//定义一个struct input_dev指针
static struct input_dev *btn_dev;


//中断处理函数
static irqreturn_t button_isr(int irq,
void *dev_id)
{
/*1.获取每个按键的按键信息*/
struct button_resource *pbtn =
(struct button_resource *)dev_id;
unsigned int pinstatus;


/*2.获取按键状态*/
pinstatus = gpio_get_value(pbtn->gpio);


/*3.上报按键信息*/
/*3.1 唤醒休眠的进程*/
/*3.2 将数据信息上报给核心层*/
if (pinstatus == 1) {
//松开
input_event(btn_dev, EV_KEY, pbtn->code, 0);
input_sync(btn_dev);
} else {
//按下
input_event(btn_dev, EV_KEY, pbtn->code, 1);
input_sync(btn_dev);
}


return IRQ_HANDLED;
}


static int button_init(void)
{ int i;


/*1.分配input_dev*/
btn_dev = input_allocate_device();

/*2.初始化input_dev*/
/*2.1指定一个名称*/
btn_dev->name = "tarena_button";


/*2.2指定上报哪类事件*/
set_bit(EV_KEY, btn_dev->evbit); //按键类事件
set_bit(EV_REP, btn_dev->evbit); //重复类事件


/*2.3指定按键类事件的哪些事件*/
for (i = 0; i < ARRAY_SIZE(btn_info); i++) {
set_bit(btn_info[i].code, btn_dev->keybit);
}

/*3.注册input_dev*/
input_register_device(btn_dev);

/*4.申请GPIO和注册中断*/
for (i = 0; i < ARRAY_SIZE(btn_info); i++) {
gpio_request(btn_info[i].gpio,
btn_info[i].name);
request_irq(btn_info[i].irq,
button_isr,
IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
btn_info[i].name,
&btn_info[i]);
}
return 0;
}


static void button_exit(void)
{
int i;

/*1.释放GPIO和中断*/
for (i = 0; i < ARRAY_SIZE(btn_info); i++) {
free_irq(btn_info[i].irq, &btn_info[i]);
gpio_free(btn_info[i].gpio);
}

/*2.卸载input_dev*/
input_unregister_device(btn_dev);

/*3.释放input_dev*/
input_free_device(btn_dev);
}


module_init(button_init);
module_exit(button_exit);

MODULE_LICENSE("GPL v2");

*******************************************************************************

测试代码:

*******************************************************************************

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>


int main(int argc, char *argv[])
{
//定义用户和驱动交互的数据元
struct input_event button;
int fd;


fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("open failed.\n");
return -1;
}


while(1) {
read(fd, &button, sizeof(button));
printf("type = %#x, code = %#x, value = %#x\n",
button.type, button.code, button.value);
}

close(fd);
}