免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1669 | 回复: 1
打印 上一主题 下一主题

input 键盘驱动及测试 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-23 02:29 |只看该作者 |倒序浏览

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/input.h>

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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/input.h>

/*
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

 

论坛徽章:
0
2 [报告]
发表于 2013-03-25 21:25 |只看该作者
您好,请问一下,为什么我的
input_report_key(button_devp, BTN_5, down);
input_sync(button_devp);
只能报告一次(测试程序只打印一次),但是我每次都能进中断。
请问这是为什么
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP