#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "plat_input.h"
struct s5pv210_key_dev *key_dev;
int irqno;
static irqreturn_t key_irq_handler(int irq, void *dummy)
{
int value;
struct s5pv210_key_data *p;
printk("----------- ^_^ %s---------------\n",__FUNCTION__);
p = (struct s5pv210_key_data *)dummy;
value = gpio_get_value(p->gpiono);
if(value){
printk("kernel: %s up\n",p->name);
input_event(key_dev->i_dev,p->event.type,p->event.code,0);
input_sync(key_dev->i_dev);
}else{
printk("kernel: %s pressed\n",p->name);
input_report_key(key_dev->i_dev, p->event.code, 1);
input_sync(key_dev->i_dev);
}
return IRQ_HANDLED;
}
int key_plat_input_probe(struct platform_device *pdev)
{
int ret;
int i;
struct s5pv210_key_data *kinfo;
printk("----------- ^_^ %s---------------\n",__FUNCTION__);
key_dev = kzalloc(sizeof(struct s5pv210_key_dev), GFP_KERNEL);
if(!key_dev){
printk("kzalloc error");
return -ENOMEM;
}
key_dev->pd = (struct s5pv210_pdata*)pdev->dev.platform_data;
key_dev->dev = pdev->dev;
key_dev->i_dev= input_allocate_device();
if (!key_dev->i_dev) {
printk(KERN_ERR "input_allocate_device: Not enough memory\n");
ret = -ENOMEM;
goto err_kfree;
}
key_dev->i_dev->evbit[0] = BIT_MASK(key_dev->pd->type);
ret = input_register_device(key_dev->i_dev);
if (ret) {
printk(KERN_ERR "input_register_device: Failed to register device\n");
goto err_free_dev;
}
for(i=0; i < key_dev->pd->keysize;i++){
kinfo = &(key_dev->pd->keyset[i]);
irqno = gpio_to_irq(kinfo->gpiono);
if (request_irq(irqno, key_irq_handler,kinfo->flags, kinfo->name, kinfo)) {
printk(KERN_ERR "request_irq: Can't allocate irq\n");
ret = -EBUSY;
goto err_input_unregister;
}
set_bit(kinfo->event.code,key_dev->i_dev->keybit);
}
return 0;
err_input_unregister:
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 key_plat_input_remove(struct platform_device * pdev)
{
int i;
struct s5pv210_key_data *kinfo;
printk("----------- ^_^ %s---------------\n",__FUNCTION__);
for(i=0; i < key_dev->pd->keysize;i++){
kinfo = &key_dev->pd->keyset[i];
free_irq(gpio_to_irq(kinfo->gpiono), kinfo);
}
input_unregister_device(key_dev->i_dev);
input_free_device(key_dev->i_dev);
kfree(key_dev);
return 0;
}
struct platform_driver key_pdrv = {
.probe = key_plat_input_probe,
.remove = key_plat_input_remove,
.driver = {
.name = "s5pv210_key",
},
};
static int __init plat_input_drv_init(void)
{
printk("----------- ^_^ %s---------------\n",__FUNCTION__);
return platform_driver_register(&key_pdrv);
}
static void __exit plat_input_drv_exit(void)
{
printk("----------- ^_^ %s---------------\n",__FUNCTION__);
platform_driver_unregister(&key_pdrv);
}
module_init(plat_input_drv_init);
module_exit(plat_input_drv_exit);
MODULE_LICENSE("GPL");
```c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "plat_input.h"
struct s5pv210_key_data key_set[] = {
[0] = {
.name = "key_up",
.gpiono = S5PV210_GPH0(0),
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
.event = {
.type = EV_KEY,
.code = KEY_UP,
},
},
[1] = {
.name = "key_down",
.gpiono = S5PV210_GPH0(1),
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
.event = {
.type = EV_KEY,
.code = KEY_DOWN,
},
},
[2] = {
.name = "key_left",
.gpiono = S5PV210_GPH0(2),
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
.event = {
.type = EV_KEY,
.code = KEY_LEFT,
},
},
[3] = {
.name = "key_right",
.gpiono = S5PV210_GPH0(3),
.flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
.event = {
.type = EV_KEY,
.code = KEY_RIGHT,
},
},
};
void key_release(struct device *dev)
{
printk("----------- ^_^ %s -------------\n",__FUNCTION__);
}
struct s5pv210_pdata key_pdata = {
.keyset = key_set,
.keysize = ARRAY_SIZE(key_set),
.type = EV_KEY,
};
struct platform_device key_pdev = {
.name = "s5pv210_key",
.id = -1,
.dev = {
.platform_data = &key_pdata,
.release = key_release,
},
};
static int __init plat_input_dev_init(void)
{
printk("----------- ^_^ %s -------------\n",__FUNCTION__);
return platform_device_register(&key_pdev);
}
static void __exit plat_input_dev_exit(void)
{
printk("----------- ^_^ %s -------------\n",__FUNCTION__);
platform_device_unregister(&key_pdev);
}
module_init(plat_input_dev_init);
module_exit(plat_input_dev_exit);
MODULE_LICENSE("GPL");
```c
/*
plat_input.h
*/
#ifndef __PLAT_INPUT_H__
#define __PLAT_INPUT_H__
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
//按键的数据包
struct s5pv210_key_data{
char *name;
int gpiono;
int flags;
struct input_event event;
};
//设计一个平台自定义数据类型
struct s5pv210_pdata{
struct s5pv210_key_data *keyset;
int keysize;
int type;
};
//设计全局设备对象类型
struct s5pv210_key_dev{
struct input_dev *i_dev;
struct s5pv210_pdata *pd;
struct device dev;
};
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
int main(void)
{
int key_fd;
struct input_event event;
int ret;
if((key_fd = open("/dev/event0",O_RDWR)) < 0){
perror("open");
exit(1);
}
while(1){
bzero(&event,sizeof(event));
if((ret = read(key_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");
}
}
}
close(key_fd);
return 0;
}
```c
KERNEL_DIR = /home/peter/fs210/kerner/linux-3.0.8
CUR_DIR = ${shell pwd}
MODULE_NAME1 = plat_input_drv
MODULE_NAME2 = plat_input_dev
MYAPP = key_app
all:
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
arm-none-linux-gnueabi-gcc -o $(MYAPP) $(MYAPP).c
clean:
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
rm $(MYAPP)
install:
cp *.ko /opt/rootfs/drv_module
cp $(MYAPP) /opt/rootfs/drv_module
obj-m += $(MODULE_NAME1).o
obj-m += $(MODULE_NAME2).o