Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90479
  • 博文数量: 17
  • 博客积分: 408
  • 博客等级: 一等列兵
  • 技术积分: 210
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-24 10:11
文章分类
文章存档

2012年(1)

2011年(16)

分类: 嵌入式

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

 

阅读(2870) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~