数据结构:
#ifndef __PLAT_INPUT_H__
#define __PLAT_INPUT_H__
struct btn_info{
char * name;
int gpiono;
struct input_event event;
};
struct btn_platdata {
struct btn_info * key_set;
int key_size;
};
struct btn_input_dev{
struct device dev;
struct input_dev *i_dev;
struct btn_platdata *pd;
};
#endif
设备层:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include "plat_input.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_pdata = {
.key_set = btn_set,
.key_size = ARRAY_SIZE(btn_set),
};
void btn_input_release(struct device *dev)
{
printk("---------------%s---------------\n",__FUNCTION__);
}
struct platform_device input_pdev = {
.name = "s5pv210_key",
.id = -1,
.dev = {
.release = btn_input_release,
.platform_data = &btn_input_pdata,
},
};
static int __init plat_input_dev_init(void)
{
printk("---------------%s---------------\n",__FUNCTION__);
return platform_device_register(&input_pdev);
}
static void __exit plat_input_dev_exit(void)
{
printk("---------------%s---------------\n",__FUNCTION__);
platform_device_unregister(&input_pdev);
}
module_init(plat_input_dev_init);
module_exit(plat_input_dev_exit);
MODULE_LICENSE("GPL");
驱动层:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include "plat_input.h"
struct btn_input_dev *keydev;
int irqno;
irqreturn_t button_interrupt(int gpiono, void * pdata)
{
int value;
struct btn_info * tmp;
struct input_event event;
printk("---------------%s---------------\n",__FUNCTION__);
tmp = (struct btn_info *)pdata;
event = (struct input_event)tmp->event;
value = gpio_get_value(tmp->gpiono);
if(value)
{
event.value = 0;
input_event(keydev->i_dev, event.type,event.code,event.value);
input_sync(keydev->i_dev);
}
else
{
event.value = 1;
input_report_key(keydev->i_dev,event.code,event.value);
input_sync(keydev->i_dev);
}
return IRQ_HANDLED;
}
int input_btn_probe(struct platform_device *pdev)
{
int ret,i;
struct btn_info *kinfo;
printk("---------------%s---------------\n",__FUNCTION__);
keydev = kzalloc(sizeof(struct btn_input_dev),GFP_KERNEL);
if(keydev == NULL)
{
printk("kzalloc error");
return -ENOMEM;
}
keydev->pd = pdev->dev.platform_data;
keydev->i_dev = input_allocate_device();
if(keydev->i_dev == NULL)
{
printk("input_allocate_device error");
ret = -ENOMEM;
goto err_kfree;
}
keydev->i_dev->evbit[0] = BIT_MASK(EV_KEY);
ret = input_register_device(keydev->i_dev);
if(ret)
{
printk("input_register_device error");
goto err_free_dev;
}
for(i = 0; i < keydev->pd->key_size; i++)
{
kinfo = &keydev->pd->key_set[i];
irqno = gpio_to_irq(kinfo->gpiono);
if(request_irq(irqno,button_interrupt,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,kinfo->name,kinfo))
{
printk("request_irq error");
ret = -EBUSY;
goto err_unregister_dev;
}
set_bit(kinfo->event.code,keydev->i_dev->keybit);
}
return 0;
err_unregister_dev:
{
for(; i > 0; i--)
{
irqno = gpio_to_irq(keydev->pd->key_set[i-1].gpiono);
free_irq(irqno,&(keydev->pd->key_set[i-1]));
}
input_unregister_device(keydev->i_dev);
}
err_free_dev:
input_free_device(keydev->i_dev);
err_kfree:
kfree(keydev);
return ret;
}
int input_btn_remove(struct platform_device *pdev)
{
int i;
printk("---------------%s---------------\n",__FUNCTION__);
for(i = 0; i < keydev->pd->key_size; i++)
{
irqno = gpio_to_irq(keydev->pd->key_set[i].gpiono);
free_irq(irqno,&(keydev->pd->key_set[i]));
}
input_unregister_device(keydev->i_dev);
input_free_device(keydev->i_dev);
kfree(keydev);
return 0;
}
struct platform_driver input_pdrv = {
.probe = input_btn_probe,
.remove = input_btn_remove,
.driver = {
.name = "s5pv210_key",
},
};
static int __init plat_input_drv_init(void)
{
printk("---------------%s---------------\n",__FUNCTION__);
return platform_driver_register(&input_pdrv);
}
static void __exit plat_input_drv_exit(void)
{
printk("---------------%s---------------\n",__FUNCTION__);
platform_driver_unregister(&input_pdrv);
}
module_init(plat_input_drv_init);
module_exit(plat_input_drv_exit);
MODULE_LICENSE("GPL");
app:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
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));input子系统结构返回的event事件结构体(由中断上报影响里面的值)
if(ret < 0)
{
perror("read");
exit(1);
}
if(event.type == EV_KEY)
{
switch(event.code)
{
case KEY_UP:
if(event.value)
printf("app按下---->上键\n");
else
printf("app松开---->上键\n");
break;
case KEY_DOWN:
if(event.value)
printf("app按下---->下键\n");
else
printf("app松开---->下键\n");
break;
case KEY_LEFT:
if(event.value)
printf("app按下---->左键\n");
else
printf("app松开---->左键\n");
break;
case KEY_RIGHT:
if(event.value)
printf("app按下---->右键\n");
else
printf("app松开---->右键\n");
break;
default:
break;
}
}
}
close(fd);
return 0;
}