分类: 嵌入式
2011-10-11 13:44:05
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_AUTHOR("wjb");
MODULE_LICENSE("GPL");
struct input_dev* button_devp;
struct button_irq_desc{
int irq;
int pin;
int number;
char *name;
};
static struct button_irq_desc button_irqs[] = {
{IRQ_EINT8, S3C2410_GPG(0), 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG(3), 1, "KEY1"},
{IRQ_EINT13, S3C2410_GPG(5), 2, "KEY2"},
{IRQ_EINT14, S3C2410_GPG(6), 3, "KEY3"},
{IRQ_EINT15, S3C2410_GPG(7), 4, "KEY4"},
{IRQ_EINT19, S3C2410_GPG(11), 5, "KEY5"},
};
static irqreturn_t button_interrupt(int irq, void* dev_id)
{
struct button_irq_desc *button_irqs = (struct button_irq_desc*)dev_id;
int down;
down = !s3c2410_gpio_getpin(button_irqs->pin);
switch(button_irqs->irq)
{
case IRQ_EINT8:
input_report_key(button_devp, BTN_0, down);
input_sync(button_devp);
break;
case IRQ_EINT11:
input_report_key(button_devp, BTN_1, down);
input_sync(button_devp);
break;
case IRQ_EINT13:
input_report_key(button_devp, BTN_2, down);
input_sync(button_devp);
break;
case IRQ_EINT15:
input_report_key(button_devp, BTN_3, down);
input_sync(button_devp);
break;
case IRQ_EINT14:
input_report_key(button_devp, BTN_4, down);
input_sync(button_devp);
break;
case IRQ_EINT19:
input_report_key(button_devp, BTN_5, down);
input_sync(button_devp);
break;
default:
break;
}
return IRQ_RETVAL(IRQ_HANDLED);
}
static int __init button_init(void)
{
int i;
int err;
button_devp = input_allocate_device();
for(i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
if(button_irqs[i].irq < 0)
{
continue;
}
err = request_irq(button_irqs[i].irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, button_irqs[i].name, (void *)&button_irqs[i]);
if(err)
{
break;
}
}
if(err)
{
i--;
for(; i >= 0; i--)
{
if(button_irqs[i].irq < 0)
{
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
}
return -EBUSY;
}
set_bit(EV_KEY, button_devp->evbit);
set_bit(BTN_0, button_devp->keybit);
set_bit(BTN_1, button_devp->keybit);
set_bit(BTN_2, button_devp->keybit);
set_bit(BTN_3, button_devp->keybit);
set_bit(BTN_4, button_devp->keybit);
set_bit(BTN_5, button_devp->keybit);
input_register_device(button_devp);
return 0;
}
static void __exit button_exit(void)
{
int i = 5;
input_unregister_device(button_devp);
for(i = 5; i >= 0; i--)
{
if(button_irqs[i].irq < 0)
{
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void*)&button_irqs[i]);
}
}
module_init(button_init);
module_exit(button_exit);
这里有两点要注意:
1)button_init函数一定要返回一个值。不然虽然能编译通过,但是运行会有问题。
2)中断处理函数返回值不能是void型。据说这个是2.6内核和2.4内核的区别。同样,如果返回值为void,编译也没问题,运行会有bad_irq字样的错误。
3、Makefile
ifneq ($(KERNELRELEASE), )
obj-m := inputDev.o
else
KDIR := /usr/src/linux-2.6.32.2
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
4、make
运行make命令,会生成inputDev.ko。
5、编写应用程序appInputDev.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
struct input_event
{
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};*/
int main(void)
{
struct input_event ev_key;
int fd = open("/dev/input/event1", O_RDWR);
while(1)
{
int count = read(fd, &ev_key, sizeof(struct input_event));
if(EV_KEY == ev_key.type&&ev_key.code)
{
printf("time : %ld, %d", ev_key.time.tv_sec, ev_key.time.tv_usec);
printf(" type:%d code : %d value : %d \n", ev_key.type, ev_key.code, ev_key.value);
}
}
return 0;
}
注意:此处打开的文件是/dev/input/event1,之所以是event1,而不是event0,或者event2等等,主要是我发现系统之前已经有一个/dev/input/event0,而添加了这个设备模块后,/dev/input/event1就多出来了。但是如果我们有多个input设备同时注册,那么具体该打开的文件是哪个,我还有点不懂。
6、生成应用程序
使用命令arm-linux-gcc -o appInput appInputDev.c,将会生成应用程序appInput。
7、测试
将inputDev.ko和appInput拷贝到开发板。
1)使用insmod inputDev.ko将设备注册。
这时候,会发现/dev/input/下多出一个event1,用cat /dev/bus/input/devices,会发现一个新的虚拟设备/devices/virtual/input/input1已经存在了,其handler正是event1。(如果使用rmmod inputDev将inputDev设备模块移掉,然后再insmod inputDev.ko,会发现新的虚拟设备变成/devices/virtual/input/input2了,但是handler仍旧是event1;继续多删除模块添加模块几次,/devices/virtual/input/input*的数值会继续增长。)
2)执行./appInput,运行appInput。然后按下任意一个按键,会发现有输出:
time : 1293632357, 846429 type:1 code : 257 value : 1