按鍵驅動

主機:centos 6.7

開發板:FL2440

系統內核版本:Linux 3.0

編譯器:arm-Linux-gcc-4.5.4

芯片:Samsung S3C2400

[hongfuhao@centos6 input_kbd]$ ls

 kbd_device.c   kbd_driver.c  event_button.c  kbd_driver.h  Makefile
驅動相關頭文件kbd_driver.h:

  1. /***************************************************************************** 
  2.  *      Copyright:  (C) 2016 Guo Wenxue<[email protected]> 
  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 <[email protected]> 
  10.  *      ChangeLog:  1, Release initial version on "07/26/2016 06:54:47 PM" 
  11.  *                  
  12.  ********************************************************************************/  
  13.   
  14.   
  15. #ifndef  _KBD_DRIVER_H_  
  16. #define  _KBD_DRIVER_H_  
  17.   
  18.   
  19. /* keyboard hardware informtation structure definition */  
  20. typedef struct s3c_kbd_info_s  
  21. {  
  22.     int                     code;      /* input device key code  */  
  23.     int                     nIRQ;      /* keyboard IRQ number*/  
  24.     unsigned int            setting;   /* keyboard IRQ Pin Setting*/  
  25.     unsigned int            gpio;      /* keyboard GPIO port */  
  26. } s3c_kbd_info_t;  
  27.   
  28.   
  29. /* keyboard platform device private data structure */  
  30. typedef struct s3c_kbd_platform_data_s  
  31. {  
  32.     s3c_kbd_info_t         *keys;  
  33.     int                    nkeys;  
  34. } s3c_kbd_platform_data_t;  
  35.   
  36.   
  37. #endif   /* ----- #ifndef _KBD_DRIVER_H_  ----- */  


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

platform_driver相關驅動文件 kbd_driver.c:
  1. /********************************************************************************* 
  2.  *      Copyright:  (C) 2016 Guo Wenxue<[email protected]> 
  3.  *                  All rights reserved. 
  4.  * 
  5.  *       Filename:  kbd_driver.c 
  6.  *    Description:  This file  
  7.  *                  
  8.  *        Version:  1.0.0(07/26/2016) 
  9.  *         Author:  Guo Wenxue <[email protected]> 
  10.  *      ChangeLog:  1, Release initial version on "07/26/2016 05:01:25 PM" 
  11.  *                  
  12.  ********************************************************************************/  
  13.   
  14.   
  15. #include <linux/module.h>  
  16. #include <linux/init.h>  
  17. #include <linux/platform_device.h>  
  18. #include <linux/input.h>  
  19. #include <linux/irq.h>  
  20. #include <linux/interrupt.h>  
  21. #include <mach/hardware.h>  
  22. #include <asm/gpio.h>  
  23. #include <asm/irq.h>  
  24. #include <linux/slab.h>  
  25. #include <mach/regs-gpio.h>  
  26.   
  27.   
  28. #include "kbd_driver.h"  
  29.   
  30.   
  31. /* 1HZ=100*jiffies 1*jiffies=10ms => 1HZ=100*10ms = 1s */  
  32. #define CANCEL_DITHERING_DELAY          (HZ/50)   /* Remove button push down dithering timer delay 20ms  */   
  33.   
  34.   
  35. typedef struct s3c_kbd_s   
  36. {  
  37.     struct timer_list           *timers; /* every key get a cancel dithering timer */  
  38.     struct input_dev            *input_dev;  
  39.     s3c_kbd_platform_data_t     *pdata;  
  40. } s3c_kbd_t;  /*---  end of struct s3c_kbd_s  ---*/  
  41.   
  42.   
  43.   
  44.   
  45. s3c_kbd_t                       *s3c_kbd = NULL;  
  46.   
  47.   
  48. static irqreturn_t s3c_kbd_intterupt(int irq, void *dev_id)   
  49. {  
  50.     int                         i;  
  51.     int                         found = 0;  
  52.     struct platform_device      *pdev =  dev_id;  
  53.     s3c_kbd_t                   *s3c_kbd = NULL;  
  54.       
  55.     s3c_kbd = platform_get_drvdata(pdev);  
  56.   
  57.   
  58.     for(i=0; i<s3c_kbd->pdata->nkeys; i++)  
  59.     {  
  60.         if(irq == s3c_kbd->pdata->keys[i].nIRQ)  
  61.         {  
  62.             found = 1;  
  63.             break;  
  64.         }  
  65.     }  
  66.   
  67.   
  68.     if(!found) /*  An ERROR interrupt */  
  69.         return IRQ_NONE;  
  70.   
  71.   
  72.     mod_timer(&s3c_kbd->timers[i], jiffies+CANCEL_DITHERING_DELAY);   
  73.     return IRQ_HANDLED;    
  74. }  
  75.   
  76.   
  77. static void  cancel_dithering_timer_handler(unsigned long data)  
  78. {  
  79.     int                      which =(int)data;  
  80.     unsigned int             pinval;    
  81.   
  82.   
  83.     pinval = s3c2410_gpio_getpin(s3c_kbd->pdata->keys[which].gpio);  
  84.   
  85.   
  86.     if( pinval )   
  87.     {  
  88.         //printk("s3c_kbd key[%d] code[%d] released\n", which, s3c_kbd->pdata->keys[which].code);  
  89.         input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 0);    
  90.     }  
  91.     else  
  92.     {  
  93.         //printk("s3c_kbd key[%d] code[%d] pressed\n", which, s3c_kbd->pdata->keys[which].code);  
  94.         input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 1);    
  95.     }  
  96.       
  97.     input_sync(s3c_kbd->input_dev);  
  98. }  
  99.   
  100.   
  101. static int s3c_kbd_probe(struct platform_device *pdev)  
  102. {  
  103.     int                         i = 0;  
  104.     int                         rv = -ENOMEM;  
  105.     struct input_dev            *input_dev = NULL;  
  106.     s3c_kbd_platform_data_t     *pdata = pdev->dev.platform_data;  
  107.   
  108.   
  109.     /* malloc s3c_kbd struct */  
  110.     s3c_kbd = kmalloc(sizeof(s3c_kbd_t), GFP_KERNEL);  
  111.     if( !s3c_kbd )  
  112.     {  
  113.         printk("error: s3c_kbd_probe kmalloc() for s3c_kbd failure\n");  
  114.         goto fail;  
  115.     }  
  116.     memset(s3c_kbd, 0, sizeof(s3c_kbd_t));  
  117.   
  118.   
  119.     /* malloc cancel dithering timer for every key */  
  120.     s3c_kbd->timers = (struct timer_list *) kmalloc(pdata->nkeys*sizeof(struct timer_list), GFP_KERNEL);  
  121.     if( !s3c_kbd->timers )  
  122.     {  
  123.         printk("error: s3c_kbd_probe kmalloc() for s3c_kbd timers failure\n");  
  124.         goto fail;  
  125.     }  
  126.     memset(s3c_kbd->timers, 0, pdata->nkeys*sizeof(struct timer_list));  
  127.   
  128.   
  129.     /* malloc input_dev for keyboard */  
  130.     input_dev=input_allocate_device();  
  131.     if( !input_dev )  
  132.     {  
  133.         printk("error: s3c_kbd_probe input_allocate_device() failure\n");  
  134.         goto fail;  
  135.     }  
  136.   
  137.   
  138.     /* setup input_dev  */  
  139.     input_dev->name = pdev->name;  
  140.     input_dev->dev.parent = &pdev->dev;  
  141.     input_dev->id.bustype = BUS_HOST;  
  142.     input_dev->id.vendor = 0x0001;  
  143.     input_dev->id.product = 0x0001;  
  144.     input_dev->id.version = 0x0100;  
  145.   
  146.   
  147.     set_bit(EV_KEY,input_dev->evbit);    
  148.     set_bit(EV_REP,input_dev->evbit);   
  149.   
  150.   
  151.     /* Initialize all the keys and interrupt */  
  152.     for(i=0; i<pdata->nkeys; i++)  
  153.     {  
  154.         set_bit(pdata->keys[i].code, input_dev->keybit);  
  155.         s3c2410_gpio_cfgpin(pdata->keys[i].gpio, pdata->keys[i].setting);  
  156.         irq_set_irq_type(pdata->keys[i].nIRQ, IRQ_TYPE_EDGE_BOTH);  
  157.           
  158.         rv = request_irq(pdata->keys[i].nIRQ, s3c_kbd_intterupt, IRQF_DISABLED, pdev->name, pdev);  
  159.         if( rv )  
  160.         {  
  161.             printk("error: request IRQ[%d] for key<%d> failure\n", pdata->keys[i].nIRQ, i);  
  162.             rv = -EBUSY;  
  163.             goto fail;  
  164.         }  
  165.           
  166.         //printk("s3c_kbd request IRQ[%d] for key<%d> ok\n", pdata->keys[i].nIRQ, i);  
  167.   
  168.   
  169.          /* Initialize all the keys cancel dithering timer */  
  170.         setup_timer(&s3c_kbd->timers[i], cancel_dithering_timer_handler, i);  
  171.     }  
  172.   
  173.   
  174.     /* register input device */  
  175.     rv = input_register_device(input_dev);  
  176.     if( rv )  
  177.     {  
  178.         printk("error: s3c_kbd_probe input_register_device error!\n");  
  179.         goto fail;  
  180.     }  
  181.   
  182.   
  183.     /* set s3c_kbd as private data in pdev */  
  184.     s3c_kbd->input_dev = input_dev;  
  185.     s3c_kbd->pdata = pdata;  
  186.     platform_set_drvdata(pdev, s3c_kbd);  
  187.   
  188.   
  189.     printk("s3c_kbd_probe ok\n");  
  190.     return 0;  
  191.   
  192.   
  193. fail:  
  194.     while(i--)  
  195.     {  
  196.         disable_irq(pdata->keys[i].nIRQ);  
  197.         free_irq(pdata->keys[i].nIRQ, pdev);  
  198.         del_timer( &s3c_kbd->timers[i] );  
  199.     }  
  200.   
  201.   
  202.     if(input_dev)  
  203.     {  
  204.         input_free_device(input_dev);  
  205.     }  
  206.   
  207.   
  208.     if(s3c_kbd && s3c_kbd->timers)  
  209.     {  
  210.         kfree(s3c_kbd->timers);  
  211.     }  
  212.   
  213.   
  214.     if(s3c_kbd)  
  215.     {  
  216.         kfree(s3c_kbd);  
  217.     }  
  218.     printk("s3c_kbd_probe failed\n");  
  219.   
  220.   
  221.     return -ENODEV;  
  222. }  
  223.   
  224.   
  225. static int s3c_kbd_remove(struct platform_device *pdev)  
  226. {  
  227.     int                         i = 0;  
  228.     s3c_kbd_t                   *s3c_kbd = platform_get_drvdata(pdev);  
  229.   
  230.   
  231.     for(i=0; i<s3c_kbd->pdata->nkeys; i++)  
  232.     {  
  233.         del_timer( &s3c_kbd->timers[i] );  
  234.         disable_irq(s3c_kbd->pdata->keys[i].nIRQ);  
  235.         free_irq(s3c_kbd->pdata->keys[i].nIRQ, pdev);  
  236.     }  
  237.   
  238.   
  239.     input_unregister_device(s3c_kbd->input_dev);  
  240.   
  241.   
  242.     kfree(s3c_kbd->timers);  
  243.     kfree(s3c_kbd);  
  244.   
  245.   
  246.     printk("s3c_kbd_remove ok\n");  
  247.   
  248.   
  249.     return 0;  
  250. }  
  251.   
  252.   
  253. static struct platform_driver s3c_keyboard_driver = {  
  254.      .probe      = s3c_kbd_probe,  
  255.      .remove     = s3c_kbd_remove,  
  256.      .driver     = {  
  257.          .name       = "s3c_kbd",  
  258.          .owner      = THIS_MODULE,  
  259.      },  
  260. };  
  261.   
  262.   
  263. static int __init s3c_keyboard_drv_init(void)  
  264. {  
  265.     int            rv;  
  266.   
  267.   
  268.     rv = platform_driver_register(&s3c_keyboard_driver);  
  269.     if(rv)  
  270.     {  
  271.         printk("s3c keyboard platform driver register failure\n");  
  272.         return rv;  
  273.     }  
  274.   
  275.   
  276.     printk("s3c keyboard platform driver register ok\n");  
  277.     return 0;  
  278. }  
  279.   
  280.   
  281. static void __exit s3c_keyboard_drv_exit(void)  
  282. {  
  283.     printk("s3c keyboard driver exit\n");  
  284.   
  285.   
  286.     platform_driver_unregister(&s3c_keyboard_driver);  
  287.     return ;  
  288. }  
  289.   
  290.   
  291. module_init(s3c_keyboard_drv_init);  
  292. module_exit(s3c_keyboard_drv_exit);  
  293.   
  294.   
  295. MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_driver");  
  296. MODULE_AUTHOR("Guo Wenxue<[email protected]>");  
  297. MODULE_LICENSE("GPL");  
  298. MODULE_ALIAS("platform:FL2440 keyboard driver");  

驅動測試文件event_button.c:
  1. /********************************************************************************* 
  2.  *      Copyright:  (C) 2012 Guo Wenxue<Email:[email protected] QQ:281143292> 
  3.  *                  All rights reserved. 
  4.  * 
  5.  *       Filename:  event_button.c 
  6.  *    Description:  This file used to test GPIO button driver builtin Linux kernel on ARM board 
  7.  *                  
  8.  *        Version:  1.0.0(07/13/2012~) 
  9.  *         Author:  Guo Wenxue <[email protected]> 
  10.  *      ChangeLog:  1, Release initial version on "07/13/2012 02:46:18 PM" 
  11.  *                  
  12.  ********************************************************************************/  
  13.   
  14.   
  15. #include <stdio.h>  
  16. #include <unistd.h>  
  17. #include <errno.h>  
  18. #include <string.h>  
  19. #include <stdlib.h>  
  20. #include <unistd.h>  
  21. #include <fcntl.h>  
  22. #include <libgen.h>  
  23. #include <getopt.h>  
  24. #include <sys/types.h>  
  25. #include <sys/ioctl.h>  
  26. #include <linux/input.h>  
  27. #include <linux/kd.h>  
  28. #include <linux/keyboard.h>  
  29.   
  30.   
  31. #if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */  
  32. struct input_event   
  33. {  
  34.     struct timeval time;  
  35.     __u16 type;  /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/  
  36.     __u16 code;  /* key value, which key */  
  37.     __s32 value; /* 1: Pressed  0:Not pressed  2:Always Pressed */  
  38. };    
  39. #endif  
  40.   
  41.   
  42. #define TRUE               1  
  43. #define FALSE              0  
  44.   
  45.   
  46. #define EV_RELEASED        0  
  47. #define EV_PRESSED         1  
  48. #define EV_REPEAT          2  
  49.   
  50.   
  51. #define BUTTON_CNT         5  
  52.   
  53.   
  54. #define MODE_POLL          0x01  
  55. #define MODE_NORMAL        0x02  
  56.   
  57.   
  58. void usage(char *name);  
  59. void display_button_event(struct input_event *ev, int cnt);  
  60.   
  61.   
  62. int main(int argc, char **argv)  
  63. {  
  64.     char                  *kbd_dev = NULL;  
  65.     char                  kbd_name[256] = "Unknown";  
  66.     int                   kbd_fd = -1;  
  67.   
  68.   
  69.     int                   rv, opt;  
  70.     int                   mode = MODE_NORMAL;  
  71.     int                   size = sizeof (struct input_event);  
  72.   
  73.   
  74.     struct input_event    ev[BUTTON_CNT];   
  75.   
  76.   
  77.     struct option long_options[] = {  
  78.         {"device", required_argument, NULL, 'd'},  
  79.         {"poll", no_argument, NULL, 'p'},  
  80.         {"help", no_argument, NULL, 'h'},  
  81.         {NULL, 0, NULL, 0}  
  82.     };  
  83.   
  84.   
  85.     while ((opt = getopt_long(argc, argv, "d:ph", long_options, NULL)) != -1)  
  86.     {   
  87.         switch (opt)  
  88.         {  
  89.             case 'd':  
  90.                 kbd_dev = optarg;  
  91.                 break;  
  92.   
  93.   
  94.             case 'p':  
  95.                 mode = MODE_POLL;  
  96.                 break;  
  97.   
  98.   
  99.             case 'h':  
  100.                 usage(argv[0]);  
  101.                 return 0;  
  102.   
  103.   
  104.             default:  
  105.                 break;  
  106.         }  
  107.     }  
  108.   
  109.   
  110.     if(NULL == kbd_dev)  
  111.     {  
  112.         usage(argv[0]);  
  113.         return -1;  
  114.     }  
  115.   
  116.   
  117.     if ((getuid ()) != 0)  
  118.         printf ("You are not root! This may not work...\n");  
  119.   
  120.   
  121.   
  122.   
  123.     if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0)  
  124.     {  
  125.         printf("Open %s failure: %s", kbd_dev, strerror(errno));  
  126.         return -1;  
  127.     }  
  128.   
  129.   
  130.     ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name);  
  131.     printf ("Monitor input device %s (%s) event with %s mode:\n", kbd_dev, kbd_name, MODE_POLL==mode?"poll":"infilit loop");  
  132.   
  133.   
  134.   
  135.   
  136. #if 0 /* Not implement in the Linux GPIO button driver */  
  137.     unsigned char key_b[BUTTON_CNT/8 + 1];  
  138.     memset(key_b, 0, sizeof(key_b));  
  139.     if(ioctl(kbd_fd, EVIOCGKEY(sizeof(key_b)), key_b) < 0)  
  140.     {  
  141.         printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));  
  142.         return -1;  
  143.     }  
  144. #endif  
  145.   
  146.   
  147. #if 0 /* Not implement in the Linux GPIO button driver */  
  148.     /* rep[0]è?¨?¤???¨??‰é”?é???¤??????°????‰? delay????—?é—?,rep[1]è?¨?¤???‰é”?é???¤??????°????—?é—?é—?é?”?€? */  
  149.     int rep[2] ={2500, 1000} ;  
  150.     if(ioctl(kbd_fd, EVIOCSREP, rep) < 0)  
  151.     {  
  152.         printf("EVIOCSREP ioctl get error: %s\n", strerror(errno));  
  153.         return -1;  
  154.     }  
  155.   
  156.   
  157.     if(ioctl(kbd_fd, EVIOCGREP, rep) < 0)  
  158.     {  
  159.         printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));  
  160.         return -1;  
  161.     }  
  162.     else  
  163.     {  
  164.         printf("repeate speed: [0]= %d, [1] = %d/n", rep[0], rep[1]);  
  165.     }  
  166. #endif  
  167.   
  168.   
  169.     while (1)  
  170.     {  
  171.         if(MODE_POLL==mode)  
  172.         {  
  173.             fd_set rds;  
  174.             FD_ZERO(&rds);  
  175.             FD_SET(kbd_fd, &rds);  
  176.   
  177.   
  178.             rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);  
  179.             if (rv < 0)  
  180.             {  
  181.                 printf("Select() system call failure: %s\n", strerror(errno));  
  182.                 goto CleanUp;  
  183.             }  
  184.             else if (FD_ISSET(kbd_fd, &rds))  
  185.             {   
  186.                 if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)  
  187.                 {  
  188.                     printf("Reading data from kbd_fd failure: %s\n", strerror(errno));  
  189.                     break;  
  190.                 }  
  191.                 else  
  192.                 {  
  193.                     display_button_event(ev, rv/size);  
  194.                 }  
  195.             }  
  196.         }  
  197.         else  
  198.         {  
  199.             if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)  
  200.             {  
  201.                 printf("Reading data from kbd_fd failure: %s\n", strerror(errno));  
  202.                 break;  
  203.             }  
  204.             else  
  205.             {  
  206.                 display_button_event(ev, rv/size);  
  207.             }  
  208.         }  
  209.     }  
  210.   
  211.   
  212. CleanUp:  
  213.     close(kbd_fd);  
  214.   
  215.   
  216.     return 0;  
  217. }  
  218.   
  219.   
  220. void usage(char *name)  
  221. {  
  222.     char *progname = NULL;  
  223.     char *ptr = NULL;  
  224.   
  225.   
  226.     ptr = strdup(name);  
  227.     progname = basename(ptr);  
  228.   
  229.   
  230.     printf("Usage: %s [-p] -d <device>\n", progname);  
  231.     printf(" -d[device  ] button device name\n");  
  232.     printf(" -p[poll    ] Use poll mode, or default use infinit loop.\n");  
  233.     printf(" -h[help    ] Display this help information\n");   
  234.   
  235.   
  236.     free(ptr);  
  237.   
  238.   
  239.     return;  
  240. }  
  241.   
  242.   
  243. void display_button_event(struct input_event *ev, int cnt)  
  244. {  
  245.     int i;  
  246.     struct timeval        pressed_time, duration_time;  
  247.   
  248.   
  249.     for(i=0; i<cnt; i++)  
  250.     {  
  251.         //printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value);  
  252.         if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value)  
  253.         {  
  254.             if(BTN_1 == ev[i].code)  
  255.             {  
  256.                 pressed_time = ev[i].time;  
  257.                 printf("S1 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);  
  258.             }  
  259.             else if(BTN_2 == ev[i].code)  
  260.             {  
  261.                 pressed_time = ev[i].time;  
  262.                 printf("S2 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);  
  263.             }  
  264.             else if(BTN_3 == ev[i].code)  
  265.             {  
  266.                 pressed_time = ev[i].time;  
  267.                 printf("S3 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);  
  268.             }  
  269.             else if(BTN_4 == ev[i].code)  
  270.             {  
  271.                 pressed_time = ev[i].time;  
  272.                 printf("S4 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);  
  273.             }  
  274.             else  
  275.             {  
  276.                 pressed_time = ev[i].time;  
  277.                 printf("button key[%d]  pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);  
  278.             }  
  279.         }  
  280.         if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value)  
  281.         {  
  282.             if(BTN_1 == ev[i].code)  
  283.             {  
  284.                 timersub(&ev[i].time, &pressed_time, &duration_time);  
  285.                 printf("S1 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);  
  286.                 printf("S1 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);  
  287.             }  
  288.             else if(BTN_2 == ev[i].code)  
  289.             {  
  290.                 timersub(&ev[i].time, &pressed_time, &duration_time);  
  291.                 printf("S2 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);  
  292.                 printf("S2 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);  
  293.             }  
  294.             else if(BTN_3 == ev[i].code)  
  295.             {  
  296.                 timersub(&ev[i].time, &pressed_time, &duration_time);  
  297.                 printf("S3 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);  
  298.                 printf("S3 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);  
  299.             }  
  300.             else if(BTN_4 == ev[i].code)  
  301.             {  
  302.                 timersub(&ev[i].time, &pressed_time, &duration_time);  
  303.                 printf("S4 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);  
  304.                 printf("S4 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);  
  305.             }  
  306.             else  
  307.             {  
  308.                 timersub(&ev[i].time, &pressed_time, &duration_time);  
  309.                 printf("button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);  
  310.                 printf("button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);  
  311.             }  
  312.         }  
  313.     } /*  for(i=0; i<cnt; i++) */  
  314. }  

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

[hongfuhao@centos6 input_kbd]$ make
make[1]: Entering directory `/home/leiyuxing/fl2440/kernel/linux-3.0'
  CC [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.o
  CC [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.o
  Building modules, stage 2.
  MODPOST 2 modules
  CC      /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.mod.o
  LD [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_device.ko
  CC      /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.mod.o
  LD [M]  /home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd/kbd_driver.ko
make[1]: Leaving directory `/home/leiyuxing/fl2440/kernel/linux-3.0'
make[1]: Entering directory `/home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd'
make[1]: Leaving directory `/home/leiyuxing/fl2440/kernel/linux-3.0/input_dev/input_kbd'
[hongfuhao@centos6 input_kbd]$ ls
kbd_device.c   kbd_driver.c  kbd_driver.ko
event_button.c  kbd_device.ko  kbd_driver.h  Makefile
[hongfuhao@centos6input_kbd]$/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc
event_button.c
[hongfuhao@centos6 input_kbd]$ ls
a.out           kbd_device.c   kbd_driver.c  kbd_driver.ko
event_button.c  kbd_device.ko  kbd_driver.h  Makefile

在開發板上的操作:
下載設備驅動:
>: tftp -gr kbd_device.ko 192.168.1.2
kbd_device.ko        100% |*******************************|  3358   0:00:00 ETA
>: tftp -gr kbd_driver.ko 192.168.1.2
kbd_driver.ko        100% |*******************************|  5996   0:00:00 ETA
運行測試
>: insmod kbd_device.ko    
S3C keyboard platform device register ok
>: insmod kbd_driver.ko    
input: s3c_kbd as /devices/platform/s3c_kbd.1/input/input0
s3c_kbd_probe ok
s3c keyboard platform driver register ok
使用測試程序a.out分別測試4個按鍵:
>: ./a.out 
Usage: a.out [-p] -d <device>
 -d[device  ] button device name
 -p[poll    ] Use poll mode, or default use infinit loop.
 -h[help    ] Display this help information
>: ./a.out -p -d /dev/event0 
Monitor input device /dev/event0 (s3c_kbd) event with poll mode:
Monitor input device /dev/event0 (s3c_kbd) event with poll mode:
button key[2]  pressed time: 483.320105
button key[2] released time: 483.500073
button key[2] duration time: 1094956827.500065
button key[3]  pressed time: 485.265110
button key[3] released time: 485.520131
button key[3] duration time: 1094956829.520123
button key[4]  pressed time: 487.815109
button key[4] released time: 488.60077
button key[4] duration time: 1094956832.60069
測試發現我的按鍵4壞了故無法顯示。
發佈了44 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章