//平台设备
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include "input_button.h"
//按键信息
struct btn_info btn_set[] = {
[0] = {
.name = "key_up",
.gpiono = S5PV210_GPH0(0),
.event = {
.type = EV_KEY,
.code = KEY_UP,
},
},
[1] = {
.name = "key_down",
.gpiono = S5PV210_GPH0(1),
.event = {
.type = EV_KEY,
.code = KEY_DOWN,
},
},
[2] = {
.name = "key_left",
.gpiono = S5PV210_GPH0(2),
.event = {
.type = EV_KEY,
.code = KEY_LEFT,
},
},
[3] = {
.name = "key_right",
.gpiono = S5PV210_GPH0(3),
.event = {
.type = EV_KEY,
.code = KEY_RIGHT,
},
},
};
struct btn_platdata btn_input_data = {
.key_set = btn_set,
.key_size = ARRAY_SIZE(btn_set),
};
void input_button_dev_release(struct device *dev)
{
}
struct platform_device pdev = {
.name = "s5pv210_buttons",
.id = -1,
.dev = {
.release = input_button_dev_release,
//.platform_data = &btn_input_data,
},
};
void __init input_button_dev_set_platdata(struct btn_platdata *pd)
{
struct btn_platdata *npd;
if (!pd) {
printk(KERN_ERR "%s: no platform data\n", __func__);
return;
}
npd = kmemdup(pd, sizeof(struct btn_platdata), GFP_KERNEL);
if (!npd)
{
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
return;
}
pdev.dev.platform_data = npd;
}
static int __init input_button_dev_init(void)
{
input_button_dev_set_platdata(&btn_input_data);
return platform_device_register(&pdev);
}
static void __exit input_button_dev_exit(void)
{
platform_device_unregister(&pdev);
}
module_init(input_button_dev_init);
module_exit(input_button_dev_exit);
MODULE_LICENSE("GPL");
//平台驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include "input_button.h"
struct s5pv210_button{
struct input_dev * dev;
struct btn_platdata * pd;
};
struct s5pv210_button * button;
irqreturn_t input_button_handler(int irq, void * data)
{
int value;
struct btn_info * info;
struct input_event event;
info = (struct btn_info *)data;
event = info->event;
value = gpio_get_value(info->gpiono);
if(value)//松开
{
event.value = 0;
input_report_key(button->dev, event.code, event.value);
input_sync(button->dev);
}
else
{
event.value = 1;
input_event(button->dev, EV_KEY, event.code, event.value);
input_sync(button->dev);
}
return IRQ_HANDLED;
}
int input_button_drv_probe(struct platform_device * pdev)
{
int ret,i;
int irqno;
struct btn_info * key_info;
// 1.创建全局的结构体对象
button = kzalloc(sizeof(struct s5pv210_button), GFP_KERNEL);
if(button == NULL)
{
printk("kzalloc error\n");
return -ENOMEM;
}
button->pd = pdev->dev.platform_data;
// 2.创建input_dev对象
button->dev = input_allocate_device();
if(IS_ERR(button->dev))
{
printk("input_allocate_device error\n");
ret = PTR_ERR(button->dev);
goto kzalloc_err;
}
// 3.初始化input_dev对象
button->dev->name = "s5pv210_key_up";
//button->dev->evbit[0] |= BIT_MASK(EV_KEY);//(1 << 1)
__set_bit(EV_KEY, button->dev->evbit);
//清零
//clear_bit(nr, p)
// 4.注册input_dev对象
ret = input_register_device(button->dev);
if(ret < 0)
{
printk("input_register_device error\n");
goto input_allocate_device_err;
}
// 5.注册中断
for(i = 0; i < button->pd->key_size; i++)
{
key_info = &button->pd->key_set[i];
irqno = gpio_to_irq(key_info->gpiono);
ret = request_irq(irqno, input_button_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, key_info->name, key_info);
if(ret < 0)
{
printk("request_irq error\n");
goto input_register_device_err;
}
//button->dev->keybit[BIT_WORD(key_info->event.code)] |= BIT_MASK(key_info->event.code);//(1 << (103 % 32))
set_bit(key_info->event.code, button->dev->keybit);
}
return 0;
input_register_device_err:
{
for(; i > 0; i++)
{
irqno = gpio_to_irq(button->pd->key_set[i-1].gpiono);
free_irq(irqno, &(button->pd->key_set[i-1]));
}
input_unregister_device(button->dev);
}
input_allocate_device_err:
input_free_device(button->dev);
kzalloc_err:
kfree(button);
return ret;
}
int input_button_drv_remove(struct platform_device * pdev)
{
int i;
int irqno;
for(i = 0; i < button->pd->key_size; i++)
{
irqno = gpio_to_irq(button->pd->key_set[i].gpiono);
free_irq(irqno, &(button->pd->key_set[i]));
}
input_unregister_device(button->dev);
input_free_device(button->dev);
kfree(button);
return 0;
}
struct platform_driver pdrv = {
.probe = input_button_drv_probe,
.remove = input_button_drv_remove,
.driver = {
.name = "s5pv210_buttons",
},
};
static int __init input_button_drv_init(void)
{
return platform_driver_register(&pdrv);
}
static void __exit input_button_drv_exit(void)
{
platform_driver_unregister(&pdrv);
}
module_init(input_button_drv_init);
module_exit(input_button_drv_exit);
MODULE_LICENSE("GPL");
//应用层
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <linux/input.h>
int main(void)
{
int fd;
int ret;
struct input_event event;
fd = open("/dev/event0", O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
while(1)
{
ret = read(fd, &event, sizeof(struct input_event));
if(ret < 0)
{
perror("read");
exit(1);
}
if(event.type == EV_KEY)
{
switch(event.code)
{
case KEY_UP:
{
if(event.value)
{
printf("KEY_UP--->pressed\n");
}
else
{
printf("KEY_UP--->release\n");
}
}
break;
case KEY_DOWN:
{
if(event.value)
{
printf("KEY_DOWN--->pressed\n");
}
else
{
printf("KEY_DOWN--->release\n");
}
}
break;
case KEY_LEFT:
{
if(event.value)
{
printf("KEY_LEFT--->pressed\n");
}
else
{
printf("KEY_LEFT--->release\n");
}
}
break;
case KEY_RIGHT:
{
if(event.value)
{
printf("KEY_RIGHT--->pressed\n");
}
else
{
printf("KEY_RIGHT--->release\n");
}
}
break;
default:
break;
}
}
}
close(fd);
return 0;
}