当前位置: 代码迷 >> 综合 >> MINI2440 按键输入子系统 驱动及测试代码分析
  详细解决方案

MINI2440 按键输入子系统 驱动及测试代码分析

热度:45   发布时间:2023-12-18 21:44:49.0

按键输入子系统驱动:

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/errno.h> /* for -EBUSY */
#include <linux/ioport.h> /* for request_region */
#include <linux/delay.h> /* for loops_per_jiffy */
#include <asm/io.h>   /* for inb_p, outb_p, inb, outb, etc. */
#include <asm/uaccess.h> /* for get_user, etc. */
#include <linux/wait.h>  /* for wait_queue */
#include <linux/init.h>  /* for __init, module_{init,exit} */
#include <linux/poll.h>  /* for POLLIN, etc. */
#include <asm/mach/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/gpio.h>
#include <mach/regs-gpio.h>
#include <linux/input.h>

struct pin_desc {
    int     irq;
    int     pin;
    int     pin_state;
    char    *name;
    int     key_val;
    int     pin_val;
};

static struct pin_desc buttons_pin[] = {
    {IRQ_EINT8,    S3C2410_GPG(0),   S3C2410_GPG0_EINT8,    "KEY1",   BTN_0},
    {IRQ_EINT11,   S3C2410_GPG(3),   S3C2410_GPG3_EINT11,   "KEY3",   BTN_1},
    {IRQ_EINT13,   S3C2410_GPG(5),   S3C2410_GPG5_EINT13,   "KEY2",   BTN_2},
    {IRQ_EINT14,   S3C2410_GPG(6),   S3C2410_GPG6_EINT14,   "KEY4",   BTN_3},
    {IRQ_EINT15,   S3C2410_GPG(7),   S3C2410_GPG7_EINT15,   "KEY5",   BTN_4},
    {IRQ_EINT19,   S3C2410_GPG(11),  S3C2410_GPG11_EINT19,  "KEY6",   BTN_5},
};

static struct input_dev *buttons_input;

static irqreturn_t buttons_interrupt(int irq,void *dev_id)
{
    struct pin_desc *pin_desc = (struct pin_desc *)dev_id;
    int val;
    val = s3c2410_gpio_getpin(pin_desc->pin);

    input_event(buttons_input,EV_KEY,pin_desc->key_val, !val);
    input_sync(buttons_input);

    return IRQ_HANDLED;
}

static int __init buttons_init(void)
{
    int error;
    int i;

    buttons_input = input_allocate_device();
    if(!buttons_input)
        return  -ENOMEM;

#if 0
    buttons_input->evbit[0] = BIT(EV_KEY);

    buttons_input->keybit[BITS_TO_LONGS(KEY_L)] = BIT(KEY_L);
    buttons_input->keybit[BITS_TO_LONGS(KEY_S)] = BIT(KEY_S);
    buttons_input->keybit[BITS_TO_LONGS(KEY_ENTER)] = BIT(KEY_ENTER);
    buttons_input->keybit[BITS_TO_LONGS(KEY_LEFTSHIFT)] = BIT(KEY_LEFTSHIFT);
#endif

    set_bit(EV_KEY,buttons_input->evbit);

    for(i = 0;i<sizeof(buttons_pin)/sizeof(buttons_pin[0]);i++)
    {
        set_bit(buttons_pin[i].key_val,buttons_input->keybit);
    }

    error = input_register_device(buttons_input);
    if(error){
        input_free_device(buttons_input);
        return -1;
    }
   
    for(i = 0;i<sizeof(buttons_pin)/sizeof(buttons_pin[0]);i++)
    {
       s3c2410_gpio_cfgpin(buttons_pin[i].pin,buttons_pin[i].pin_state);
       request_irq(buttons_pin[i].irq,buttons_interrupt, IRQF_SHARED | IRQF_TRIGGER_RISING
               | IRQF_TRIGGER_FALLING,buttons_pin[i].name,(void *)&buttons_pin[i]);
    }
   
    return 0;

}
static void __exit buttons_exit(void)
{
    int i;
   
    for(i = 0; i< sizeof(buttons_pin)/sizeof(buttons_pin[0]); i++)
    {
        free_irq(buttons_pin[i].irq, (void *)&buttons_pin[i]);
    }

    input_unregister_device(buttons_input);
    input_free_device(buttons_input);
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("RopenYuan");

 

按键输入子系统测试程序

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <linux/input.h>

int main(void)
{
 int buttons_fd;
 int key_value,i=0,count;

 struct input_event ev_key;
 buttons_fd = open("/dev/input/event0", O_RDWR);
 if (buttons_fd < 0) {
  perror("open device buttons");
  exit(1);
 }

 for (;;) {
  count = read(buttons_fd,&ev_key,sizeof(struct input_event));
  for(i=0; i<(int)count/sizeof(struct input_event); i++)
   if(EV_KEY==ev_key.type)
    printf("type:%d,code:%d,value:%d\n", ev_key.type,ev_key.code,ev_key.value);

   if(EV_SYN==ev_key.type)
    printf("syn event\n\n");

    }

 close(buttons_fd);
 return 0;
}

 

MAKEFILE

ifneq ($(KERNELRELEASE),)

obj-m := buttons.o

else
  
#KDIR := /home/yuanpengjun/home/linuxeditorkernelfilesystem/kernal/linux-2.6.32/linux-2.6.32.2/
KDIR := /home/yuanpengjun/mini2440/kernel/linux-2.6.32.2/
all:
#  make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
  make -C $(KDIR) M=$(PWD) modules
  /home/yuanpengjun/mini2440/editor/4.4.3/bin/arm-none-linux-gnueabi-gcc -o button button_app.c

clean:
  rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*

endif

 

 

以上驱动代码未加入容错处理,只是为了验证是否能成功运行。

 

在模块加载时出现input: Unspecified device as /devices/virtual/input/input0  

原因为没有在驱动中设置struct input_dev 中的成员名name,若有成员名为 XXXX->name = "yyyyyyy",驱动模块加载后会出现如下情况:

input: yyyyyyy as /devices/virtual/input/input0  

 

在模块卸载时出现rmmod: chdir(2.6.32.2): No such file or directory,并且不能将模块从系统中卸载掉;

原因为:现在的内核模块在插入卸载时都会要转到/lib/modules/内核版本号/ 这个目录里,格式为/lib/modules/2.6.32.2/ 在这种情况下,不会再出现模块不能卸载情况;