linux-3.0下input_dev模型按键驱动

  该代码在FL2440开发板上测试通过,为方便教学,将驱动中的platform_device和platform_driver故意分为两个驱动模块。

 

[guowenxue@centos6 input_kbd]$ ls
event_button.c  kbd_device.c  kbd_driver.c  kbd_driver.h  Makefile 

 

驱动相关头文件 kbd_driver.h:

 1 /********************************************************************************
 2  *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
 3  *                  All rights reserved.
 4  *
 5  *       Filename:  kbd_driver.h
 6  *    Description:  This head file is for s3c keyboard driver
 7  *
 8  *        Version:  1.0.0(07/26/2016)
 9  *         Author:  Guo Wenxue <guowenxue@aliyun.com>
10  *      ChangeLog:  1, Release initial version on "07/26/2016 06:54:47 PM"
11  *                 
12  ********************************************************************************/
13 
14 #ifndef  _KBD_DRIVER_H_
15 #define  _KBD_DRIVER_H_
16 
17 /* keyboard hardware informtation structure definition */
18 typedef struct s3c_kbd_info_s
19 {
20     int                     code;      /* input device key code  */
21     int                     nIRQ;      /* keyboard IRQ number*/
22     unsigned int            setting;   /* keyboard IRQ Pin Setting*/
23     unsigned int            gpio;      /* keyboard GPIO port */
24 } s3c_kbd_info_t;
25 
26 /* keyboard platform device private data structure */
27 typedef struct s3c_kbd_platform_data_s
28 {
29     s3c_kbd_info_t         *keys;
30     int                    nkeys;
31 } s3c_kbd_platform_data_t;
32 
33 #endif   /* ----- #ifndef _KBD_DRIVER_H_  ----- */

 

platform_device相关驱动文件 kbd_device.c:

  1 /*********************************************************************************
  2  *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
  3  *                  All rights reserved.
  4  *
  5  *       Filename:  kbd_device.c
  6  *    Description:  This file 
  7  *                 
  8  *        Version:  1.0.0(07/26/2016)
  9  *         Author:  Guo Wenxue <guowenxue@aliyun.com>
 10  *      ChangeLog:  1, Release initial version on "07/26/2016 05:01:25 PM"
 11  *                 
 12  ********************************************************************************/
 13 
 14 #include <linux/module.h>
 15 #include <linux/init.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/input.h>
 18 #include <mach/hardware.h>
 19 #include <asm/gpio.h>
 20 #include <asm/irq.h>
 21 #include <mach/regs-gpio.h>
 22 #include "kbd_driver.h"
 23 
 24 static s3c_kbd_info_t  s3c_kbd_gpios[] = {
 25     [0] = {
 26         .code = KEY_1,
 27         .nIRQ = IRQ_EINT0,
 28         .gpio = S3C2410_GPF(0),
 29         .setting = S3C2410_GPF0_EINT0,
 30     },
 31     [1] = {
 32         .code = KEY_2,
 33         .nIRQ = IRQ_EINT2,
 34         .gpio = S3C2410_GPF(2),
 35         .setting = S3C2410_GPF2_EINT2,
 36     },
 37     [2] = {
 38         .code = KEY_3,
 39         .nIRQ = IRQ_EINT3,
 40         .gpio = S3C2410_GPF(3),
 41         .setting = S3C2410_GPF3_EINT3,
 42     },
 43     [3] = {
 44         .code = KEY_4,
 45         .nIRQ = IRQ_EINT4,
 46         .gpio = S3C2410_GPF(4),
 47         .setting = S3C2410_GPF4_EINT4,
 48     },
 49 };
 50 
 51 /* keyboard platform device private data */
 52 static s3c_kbd_platform_data_t s3c_kbd_data = {
 53     .keys = s3c_kbd_gpios,
 54     .nkeys = ARRAY_SIZE(s3c_kbd_gpios),
 55 };
 56 
 57 static void platform_kbd_release(struct device * dev)
 58 {
 59         return;
 60 }
 61 
 62 static struct platform_device s3c_keyboard_device = {
 63     .name    = "s3c_kbd",
 64     .id      = 1,
 65     .dev     =
 66     {
 67         .platform_data = &s3c_kbd_data,
 68         .release = platform_kbd_release,
 69     },
 70 };
 71 
 72 
 73 static int __init s3c_keyboard_dev_init(void)
 74 {
 75     int            rv;
 76 
 77     rv = platform_device_register(&s3c_keyboard_device);
 78     if(rv)
 79     {
 80         printk("S3C keyboard platform device register failure\n");
 81         return rv;
 82     }
 83 
 84     printk("S3C keyboard platform device register ok\n");
 85     return 0;
 86 }
 87 
 88 static void __exit s3c_keyboard_dev_exit(void)
 89 {
 90     printk("S3C keyboard device exit\n");
 91 
 92     platform_device_unregister(&s3c_keyboard_device);
 93     return ;
 94 }
 95 
 96 module_init(s3c_keyboard_dev_init);
 97 module_exit(s3c_keyboard_dev_exit);
 98 
 99 MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_device");
100 MODULE_AUTHOR("Guo Wenxue<guowenxue@gmail.com>");
101 MODULE_LICENSE("GPL");
102 MODULE_ALIAS("platform:FL2440 keyboard device");

 

platform_driver相关驱动文件 kbd_driver.c:

/*********************************************************************************
 *      Copyright:  (C) 2016 Guo Wenxue<guowenxue@aliyun.com>
 *                  All rights reserved.
 *
 *       Filename:  kbd_driver.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(07/26/2016)
 *         Author:  Guo Wenxue <guowenxue@aliyun.com>
 *      ChangeLog:  1, Release initial version on "07/26/2016 05:01:25 PM"
 *                 
 ********************************************************************************/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <mach/hardware.h>
#include <asm/gpio.h>
#include <asm/irq.h>
#include <linux/slab.h>
#include <mach/regs-gpio.h>

#include "kbd_driver.h"

/* 1HZ=100*jiffies 1*jiffies=10ms => 1HZ=100*10ms = 1s */
#define CANCEL_DITHERING_DELAY          (HZ/50)   /* Remove button push down dithering timer delay 20ms  */ 

typedef struct s3c_kbd_s 
{
    struct timer_list           *timers; /* every key get a cancel dithering timer */
    struct input_dev            *input_dev;
    s3c_kbd_platform_data_t     *pdata;
} s3c_kbd_t;  /*---  end of struct s3c_kbd_s  ---*/


s3c_kbd_t                       *s3c_kbd = NULL;

static irqreturn_t s3c_kbd_intterupt(int irq, void *dev_id) 
{
    int                         i;
    int                         found = 0;
    struct platform_device      *pdev =  dev_id;
    s3c_kbd_t                   *s3c_kbd = NULL;
    
    s3c_kbd = platform_get_drvdata(pdev);

    for(i=0; i<s3c_kbd->pdata->nkeys; i++)
    {
        if(irq == s3c_kbd->pdata->keys[i].nIRQ)
        {
            found = 1;
            break;
        }
    }

    if(!found) /*  An ERROR interrupt */
        return IRQ_NONE;

    mod_timer(&s3c_kbd->timers[i], jiffies+CANCEL_DITHERING_DELAY); 
    return IRQ_HANDLED;  
}

static void  cancel_dithering_timer_handler(unsigned long data)
{
    int                      which =(int)data;
    unsigned int             pinval;  

    pinval = s3c2410_gpio_getpin(s3c_kbd->pdata->keys[which].gpio);

    if( pinval ) 
    {
        //printk("s3c_kbd key[%d] code[%d] released\n", which, s3c_kbd->pdata->keys[which].code);
        input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 0);  
    }
    else
    {
        //printk("s3c_kbd key[%d] code[%d] pressed\n", which, s3c_kbd->pdata->keys[which].code);
        input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 1);  
    }
    
    input_sync(s3c_kbd->input_dev);
}

static int s3c_kbd_probe(struct platform_device *pdev)
{
    int                         i = 0;
    int                         rv = -ENOMEM;
    struct input_dev            *input_dev = NULL;
    s3c_kbd_platform_data_t     *pdata = pdev->dev.platform_data;

    /* malloc s3c_kbd struct */
    s3c_kbd = kmalloc(sizeof(s3c_kbd_t), GFP_KERNEL);
    if( !s3c_kbd )
    {
        printk("error: s3c_kbd_probe kmalloc() for s3c_kbd failure\n");
        goto fail;
    }
    memset(s3c_kbd, 0, sizeof(s3c_kbd_t));

    /* malloc cancel dithering timer for every key */
    s3c_kbd->timers = (struct timer_list *) kmalloc(pdata->nkeys*sizeof(struct timer_list), GFP_KERNEL);
    if( !s3c_kbd->timers )
    {
        printk("error: s3c_kbd_probe kmalloc() for s3c_kbd timers failure\n");
        goto fail;
    }
    memset(s3c_kbd->timers, 0, pdata->nkeys*sizeof(struct timer_list));

    /* malloc input_dev for keyboard */
    input_dev=input_allocate_device();
    if( !input_dev )
    {
        printk("error: s3c_kbd_probe input_allocate_device() failure\n");
        goto fail;
    }

    /* setup input_dev  */
    input_dev->name = pdev->name;
    input_dev->dev.parent = &pdev->dev;
    input_dev->id.bustype = BUS_HOST;
    input_dev->id.vendor = 0x0001;
    input_dev->id.product = 0x0001;
    input_dev->id.version = 0x0100;

    set_bit(EV_KEY,input_dev->evbit);  
    set_bit(EV_REP,input_dev->evbit); 

    /* Initialize all the keys and interrupt */
    for(i=0; i<pdata->nkeys; i++)
    {
        set_bit(pdata->keys[i].code, input_dev->keybit);
        s3c2410_gpio_cfgpin(pdata->keys[i].gpio, pdata->keys[i].setting);
        irq_set_irq_type(pdata->keys[i].nIRQ, IRQ_TYPE_EDGE_BOTH);
        
        rv = request_irq(pdata->keys[i].nIRQ, s3c_kbd_intterupt, IRQF_DISABLED, pdev->name, pdev);
        if( rv )
        {
            printk("error: request IRQ[%d] for key<%d> failure\n", pdata->keys[i].nIRQ, i);
            rv = -EBUSY;
            goto fail;
        }
        
        //printk("s3c_kbd request IRQ[%d] for key<%d> ok\n", pdata->keys[i].nIRQ, i);

         /* Initialize all the keys cancel dithering timer */
        setup_timer(&s3c_kbd->timers[i], cancel_dithering_timer_handler, i);
    }

    /* register input device */
    rv = input_register_device(input_dev);
    if( rv )
    {
        printk("error: s3c_kbd_probe input_register_device error!\n");
        goto fail;
    }

    /* set s3c_kbd as private data in pdev */
    s3c_kbd->input_dev = input_dev;
    s3c_kbd->pdata = pdata;
    platform_set_drvdata(pdev, s3c_kbd);

    printk("s3c_kbd_probe ok\n");
    return 0;

fail:
    while(i--)
    {
        disable_irq(pdata->keys[i].nIRQ);
        free_irq(pdata->keys[i].nIRQ, pdev);
        del_timer( &s3c_kbd->timers[i] );
    }

    if(input_dev)
    {
        input_free_device(input_dev);
    }

    if(s3c_kbd && s3c_kbd->timers)
    {
        kfree(s3c_kbd->timers);
    }

    if(s3c_kbd)
    {
        kfree(s3c_kbd);
    }
    printk("s3c_kbd_probe failed\n");

    return -ENODEV;
}

static int s3c_kbd_remove(struct platform_device *pdev)
{
    int                         i = 0;
    s3c_kbd_t                   *s3c_kbd = platform_get_drvdata(pdev);

    for(i=0; i<s3c_kbd->pdata->nkeys; i++)
    {
        del_timer( &s3c_kbd->timers[i] );
        disable_irq(s3c_kbd->pdata->keys[i].nIRQ);
        free_irq(s3c_kbd->pdata->keys[i].nIRQ, pdev);
    }

    input_unregister_device(s3c_kbd->input_dev);

    kfree(s3c_kbd->timers);
    kfree(s3c_kbd);

    printk("s3c_kbd_remove ok\n");

    return 0;
}

static struct platform_driver s3c_keyboard_driver = {
     .probe      = s3c_kbd_probe,
     .remove     = s3c_kbd_remove,
     .driver     = {
         .name       = "s3c_kbd",
         .owner      = THIS_MODULE,
     },
};

static int __init s3c_keyboard_drv_init(void)
{
    int            rv;

    rv = platform_driver_register(&s3c_keyboard_driver);
    if(rv)
    {
        printk("s3c keyboard platform driver register failure\n");
        return rv;
    }

    printk("s3c keyboard platform driver register ok\n");
    return 0;
}

static void __exit s3c_keyboard_drv_exit(void)
{
    printk("s3c keyboard driver exit\n");

    platform_driver_unregister(&s3c_keyboard_driver);
    return ;
}

module_init(s3c_keyboard_drv_init);
module_exit(s3c_keyboard_drv_exit);

MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_driver");
MODULE_AUTHOR("Guo Wenxue<guowenxue@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:FL2440 keyboard driver");

 

驱动测试文件event_button.c:

/*********************************************************************************
 *      Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
 *                  All rights reserved.
 *
 *       Filename:  event_button.c
 *    Description:  This file used to test GPIO button driver builtin Linux kernel on ARM board
 *                 
 *        Version:  1.0.0(07/13/2012~)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "07/13/2012 02:46:18 PM"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <linux/kd.h>
#include <linux/keyboard.h>

#if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */
struct input_event 
{
    struct timeval time;
    __u16 type;  /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/
    __u16 code;  /* key value, which key */
    __s32 value; /* 1: Pressed  0:Not pressed  2:Always Pressed */
};  
#endif

#define TRUE               1
#define FALSE              0

#define EV_RELEASED        0
#define EV_PRESSED         1
#define EV_REPEAT          2

#define BUTTON_CNT         5

#define MODE_POLL          0x01
#define MODE_NORMAL        0x02

void usage(char *name);
void display_button_event(struct input_event *ev, int cnt);

int main(int argc, char **argv)
{
    char                  *kbd_dev = NULL;
    char                  kbd_name[256] = "Unknown";
    int                   kbd_fd = -1;

    int                   rv, opt;
    int                   mode = MODE_NORMAL;
    int                   size = sizeof (struct input_event);

    struct input_event    ev[BUTTON_CNT]; 

    struct option long_options[] = {
        {"device", required_argument, NULL, 'd'},
        {"poll", no_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };

    while ((opt = getopt_long(argc, argv, "d:ph", long_options, NULL)) != -1)
    { 
        switch (opt)
        {
            case 'd':
                kbd_dev = optarg;
                break;

            case 'p':
                mode = MODE_POLL;
                break;

            case 'h':
                usage(argv[0]);
                return 0;

            default:
                break;
        }
    }

    if(NULL == kbd_dev)
    {
        usage(argv[0]);
        return -1;
    }

    if ((getuid ()) != 0)
        printf ("You are not root! This may not work...\n");


    if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0)
    {
        printf("Open %s failure: %s", kbd_dev, strerror(errno));
        return -1;
    }

    ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name);
    printf ("Monitor input device %s (%s) event with %s mode:\n", kbd_dev, kbd_name, MODE_POLL==mode?"poll":"infilit loop");


#if 0 /* Not implement in the Linux GPIO button driver */
    unsigned char key_b[BUTTON_CNT/8 + 1];
    memset(key_b, 0, sizeof(key_b));
    if(ioctl(kbd_fd, EVIOCGKEY(sizeof(key_b)), key_b) < 0)
    {
        printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
        return -1;
    }
#endif

#if 0 /* Not implement in the Linux GPIO button driver */
    /* rep[0]表示在按键重复出现之前 delay的时间,rep[1]表示按键重复出现的时间间隔。 */
    int rep[2] ={2500, 1000} ;
    if(ioctl(kbd_fd, EVIOCSREP, rep) < 0)
    {
        printf("EVIOCSREP ioctl get error: %s\n", strerror(errno));
        return -1;
    }

    if(ioctl(kbd_fd, EVIOCGREP, rep) < 0)
    {
        printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
        return -1;
    }
    else
    {
        printf("repeate speed: [0]= %d, [1] = %d/n", rep[0], rep[1]);
    }
#endif

    while (1)
    {
        if(MODE_POLL==mode)
        {
            fd_set rds;
            FD_ZERO(&rds);
            FD_SET(kbd_fd, &rds);

            rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);
            if (rv < 0)
            {
                printf("Select() system call failure: %s\n", strerror(errno));
                goto CleanUp;
            }
            else if (FD_ISSET(kbd_fd, &rds))
            { 
                if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
                {
                    printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                    break;
                }
                else
                {
                    display_button_event(ev, rv/size);
                }
            }
        }
        else
        {
            if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
            {
                printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                break;
            }
            else
            {
                display_button_event(ev, rv/size);
            }
        }
    }

CleanUp:
    close(kbd_fd);

    return 0;
}

void usage(char *name)
{
    char *progname = NULL;
    char *ptr = NULL;

    ptr = strdup(name);
    progname = basename(ptr);

    printf("Usage: %s [-p] -d <device>\n", progname);
    printf(" -d[device  ] button device name\n");
    printf(" -p[poll    ] Use poll mode, or default use infinit loop.\n");
    printf(" -h[help    ] Display this help information\n"); 

    free(ptr);

    return;
}

void display_button_event(struct input_event *ev, int cnt)
{
    int i;
    struct timeval        pressed_time, duration_time;

    for(i=0; i<cnt; i++)
    {
        //printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value);
        if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value)
        {
            if(BTN_1 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S1 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_2 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S2 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_3 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S3 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else if(BTN_4 == ev[i].code)
            {
                pressed_time = ev[i].time;
                printf("S4 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
            else
            {
                pressed_time = ev[i].time;
                printf("button key[%d]  pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
            }
        }
        if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value)
        {
            if(BTN_1 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S1 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S1 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_2 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S2 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S2 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_3 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S3 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S3 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else if(BTN_4 == ev[i].code)
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("S4 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("S4 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
            else
            {
                timersub(&ev[i].time, &pressed_time, &duration_time);
                printf("button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
                printf("button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
            }
        }
    } /*  for(i=0; i<cnt; i++) */
}

 

驱动和测试程序编译Makefile文件

 1 TEST_APP=event_button
 2 
 3 KERNEL_VER = linux-3.0
 4 LINUX_SRC ?= ../../linux/kernel/$(KERNEL_VER)
 5 
 6 CROSS_COMPILE=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-
 7 
 8 PWD := $(shell pwd)
 9 
10 obj-m += kbd_device.o
11 obj-m += kbd_driver.o
12 
13 modules:
14         @make -C $(LINUX_SRC) M=$(PWD) modules
15         @make clear
16         @chmod a+x *.ko && cp *.ko /tftp
17         @make testapp
18 
19 clear:
20         @rm -f *.o *.cmd *.mod.c
21         @rm -rf  *~ core .depend  .tmp_versions Module.symvers modules.order -f
22         @rm -f .*ko.cmd .*.o.cmd .*.o.d
23 
24 clean: clear
25         @rm -f  *.ko ${TEST_APP}
26 
27 testapp:
28         ${CROSS_COMPILE}gcc ${TEST_APP}.c -o ${TEST_APP}

 

编译:

[guowenxue@centos6 input_kbd]$ make
make[1]: Entering directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/linux/kernel/linux-3.0'
  CC [M]  /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_device.o
  CC [M]  /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_driver.o
  Building modules, stage 2.
  MODPOST 2 modules
  CC      /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_device.mod.o
  LD [M]  /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_device.ko
  CC      /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_driver.mod.o
  LD [M]  /usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd/kbd_driver.ko
make[1]: Leaving directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/linux/kernel/linux-3.0'
make[1]: Entering directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd'
make[1]: Leaving directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd'
make[1]: Entering directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd'
/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc event_button.c -o event_button
make[1]: Leaving directory `/usr/local/src/.guowenxue/code.taobao.org/fl2440/trunk/src/driver/input_kbd'

  

运行测试:

 列出已经安装的驱动模块
~ >: lsmod    
kbd_driver 2470 0 - Live 0xbf01c000
kbd_device 973 0 - Live 0xbf018000
~ >: 

 删除驱动的platform_driver模块
~ >: rmmod kbd_driver    
s3c keyboard driver exit
s3c_kbd_remove ok
~ >: 

 删除驱动的paltform_device模块
~ >: rmmod kbd_device   
S3C keyboard device exit
~ >: 

安装驱动的paltform_device模块
~ >: insmod kbd_device.ko    
S3C keyboard platform device register ok
~ >: 

安装驱动的platform_driver模块
~ >: insmod kbd_driver.ko    
input: s3c_kbd as /devices/platform/s3c_kbd.1/input/input6
s3c_kbd_probe ok
s3c keyboard platform driver register ok
~ >: 

使用测试程序event_button分别测试4个按键:
~ >: event_button -p -d /dev/input/event1 
Monitor input device /dev/input/event1 (s3c_kbd) event with poll mode:
button key[2]  pressed time: 1469541794.755122
button key[2] released time: 1469541794.980104
button key[2] duration time: 1469418914.857224

button key[3]  pressed time: 1469541798.625197
button key[3] released time: 1469541798.865105
button key[3] duration time: 1469418918.742225

button key[4]  pressed time: 1469541801.260260
button key[4] released time: 1469541801.535216
button key[4] duration time: 1469418921.412336

button key[5]  pressed time: 1469541803.805109
button key[5] released time: 1469541804.107
button key[5] duration time: 1469418923.877227

  

posted @ 2016-07-26 22:07  凌云物网智科实验室  阅读(1138)  评论(0编辑  收藏  举报