示例代码
1、头文件
#ifndef __INPUT_PLAT_H__
#define __INPUT_PLAT_H__
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/interrupt.h>
struct key_event{
char *name;
int gpiono;
int type;
int code;
int flags;
};
struct input_pdata{
struct key_event *keyset;
int keysize;
};
struct s5pv210_key{
struct input_pdata *pd;
struct input_dev *i_dev;
struct device dev;
};
#endif
2、pdrv
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include "input_plat.h"
struct s5pv210_key *key_dev;
int irqno;
static irqreturn_t key_interrupt_handler(int irq, void *dummy)
{
int value;
struct key_event *kevent;
printk("--------------^_^ %s---------------\n",__FUNCTION__);
kevent = (struct key_event *)dummy;
value = gpio_get_value(kevent->gpiono);
if(value){
input_report_key(key_dev->i_dev, kevent->code, 0);
input_sync(key_dev->i_dev);
}else{
input_event(key_dev->i_dev,kevent->type,kevent->code,1);
input_sync(key_dev->i_dev);
}
return IRQ_HANDLED;
}
int input_plat_probe(struct platform_device * pdev)
{
int ret,i;
struct key_event *kevent;
printk("--------------^_^ %s---------------\n",__FUNCTION__);
key_dev = kzalloc(sizeof(struct s5pv210_key), GFP_KERNEL);
if(!key_dev){
printk(KERN_ERR "Not enough memory\n");
return -ENOMEM;
}
key_dev->i_dev = input_allocate_device();
if (!key_dev->i_dev) {
printk(KERN_ERR "Not enough memory\n");
ret= -ENOMEM;
goto err_kfree;
}
key_dev->i_dev->evbit[0] = BIT_MASK(EV_KEY);
ret = input_register_device(key_dev->i_dev);
if (ret) {
printk(KERN_ERR "Failed to register device\n");
goto err_free_dev;
}
key_dev->pd = pdev->dev.platform_data;
key_dev->dev = pdev->dev;
for( i = 0; i < key_dev->pd->keysize;i++){
kevent = &key_dev->pd->keyset[i];
irqno = gpio_to_irq(kevent->gpiono);
if (request_irq(irqno, key_interrupt_handler, kevent->flags, kevent->name, kevent)) {
printk(KERN_ERR "Can't allocate irq %d\n", irqno);
ret = -EBUSY;
goto err_unregister_dev;
}
__set_bit(kevent->code, key_dev->i_dev->keybit);
}
return 0;
err_unregister_dev:
input_unregister_device(key_dev->i_dev);
err_free_dev:
input_free_device(key_dev->i_dev);
err_kfree:
kfree(key_dev);
return ret;
}
int input_plat_remove(struct platform_device *pdev)
{
int i;
printk("----------^_^ %s----------------\n",__FUNCTION__);
for(i = 0; i < key_dev->pd->keysize; i++){
irqno = gpio_to_irq(key_dev->pd->keyset[i].gpiono);
free_irq(irqno, &key_dev->pd->keyset[i]);
}
input_unregister_device(key_dev->i_dev);
input_free_device(key_dev->i_dev);
return 0;
}
struct platform_driver input_pdrv = {
.probe = input_plat_probe,
.remove = input_plat_remove,
.driver = {
.name = "input_key",
},
};
static int __init input_pdrv_init(void)
{
printk("----------^_^ %s----------------\n",__FUNCTION__);
return platform_driver_register(&input_pdrv);
}
static void __exit input_pdrv_exit(void)
{
printk("----------^_^ %s----------------\n",__FUNCTION__);
platform_driver_unregister(&input_pdrv);
}
module_init(input_pdrv_init);
module_exit(input_pdrv_exit);
MODULE_LICENSE("GPL");
3、pdev
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include "input_plat.h"
struct key_event key_set[]={
[0] = {
.name = "key_up",
.gpiono = S5PV210_GPH0(0),
.type = EV_KEY,
.code = KEY_UP,
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
},
[1] = {
.name = "key_DOWN",
.gpiono = S5PV210_GPH0(1),
.type = EV_KEY,
.code = KEY_DOWN,
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
},
[2] = {
.name = "key_left",
.gpiono = S5PV210_GPH0(2),
.type = EV_KEY,
.code = KEY_LEFT,
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
},
[3] = {
.name = "key_right",
.gpiono = S5PV210_GPH0(3),
.type = EV_KEY,
.code = KEY_RIGHT,
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
},
};
struct input_pdata key_pdata = {
.keyset = key_set,
.keysize = ARRAY_SIZE(key_set),
};
void input_key_release(struct device *dev)
{
printk("--------------^_^ %s-----------------\n",__FUNCTION__);
}
struct platform_device input_pdev = {
.name = "input_key",
.id = -1,
.dev = {
.release = input_key_release,
},
};
void __init input_set_platdata(struct input_pdata *pd)
{
struct input_pdata *npd;
if (!pd) {
printk(KERN_ERR "%s: no platform data\n", __func__);
return;
}
npd = kmemdup(pd, sizeof(struct input_pdata), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
input_pdev.dev.platform_data = npd;
}
static int __init input_pdev_init(void)
{
printk("--------------^_^ %s-----------------\n",__FUNCTION__);
input_set_platdata(&key_pdata);
return platform_device_register(&input_pdev);
}
static void __exit input_pdev_exit(void)
{
printk("--------------^_^ %s-----------------\n",__FUNCTION__);
platform_device_unregister(&input_pdev);
}
module_init(input_pdev_init);
module_exit(input_pdev_exit);
MODULE_LICENSE("GPL");
4、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(void)
{
int fd;
int ret;
struct input_event event;
if((fd = open("/dev/event0",O_RDWR)) < 0){
perror("open");
exit(1);
}
while(1){
if((ret = read(fd,&event,sizeof(event))) < 0){
perror("read");
exit(1);
}
if(event.type == EV_KEY){
switch(event.code){
case KEY_UP:
if(event.value)
printf("按下--->上键\n");
else
printf("松开--->上键\n");
break;
case KEY_DOWN:
if(event.value)
printf("按下--->下键\n");
else
printf("松开--->下键\n");
break;
case KEY_LEFT:
if(event.value)
printf("按下--->左键\n");
else
printf("松开--->左键\n");
break;
case KEY_RIGHT:
if(event.value)
printf("按下--->右键\n");
else
printf("松开--->右键\n");
break;
}
}
}
close(fd);
return 0;
}