• Linux 输入子系统驱动程序范例


    <按键驱动程序>
    #include <stdio.h>
    #include <fcntl.h>
    #include <linux/input.h>
    #include <sys/types.h>
    #include <unistd.h>
    int main(int argc, char** argv)
    {
       int fd;
       int count;
       int i = 0;
       int j = 0;
       struct input_event key2;
       //在根文件系统用cat /proc/bus/input/devices查看是event几
       fd = open("/dev/event1", O_RDWR);
     
       if (fd < 0)
       {
           perror("open");
           return -1;
       }
       while (1)
       {
           lseek(fd, 0, SEEK_SET);
           count = read(fd, &key2, sizeof(struct input_event)); 
           if(count != sizeof(struct input_event))
           {
               perror("read");
           }
           if(EV_KEY == key2.type)
           {
               printf(" i = %d, type:%d, code:%d, value:%d ", i, key2.type,                key2.code, key2.value);
               if (key2.value)
               {
                   i++;
                   printf("***********the k2 down %d times*********** ", i);    
               }
           else
           {
               printf("****************the k2 up***************** "); 
           }
       } 
     
       if(EV_SYN == key2.type)
       {
           printf("syn event ");
           if (++j == 2)
           {
               j = 0;
               printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ");
           }
       }
    }
       close(fd);
       return 0;
    }
     
    驱动程序:inputk2_drv.c
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/input.h>
    #include <linux/interrupt.h>
    #include <asm/gpio.h>
    #include <linux/timer.h>
     
    static struct input_dev *button_dev;//定义输入设备
    struct timer_list my_timer;//定义定时器结构体timer_list
    //定义定时器超时处理函数
    void timer_func(unsigned long data)
    {
    int key_value = gpio_get_value(S5PV210_GPH2(0));
    //上报事件给input核心层
    input_report_key(button_dev, KEY_A, !key_value);//按下为1
    //告诉input子系统上报已经完成
    input_sync(button_dev);
    //printk("[%d][%s], data=[%lu] ", __LINE__, __FUNCTION__, data);
    }
    static irqreturn_t button_interrupt(int irq, void *dev_id)
    {
    //the value of timeout is decided by the n of "jiffies + n" 
    //timeout = n*(1000/HZ) ms(HZ=256 in this project)
    //the empirical value of timeout ≈ 10~100ms
    mod_timer(&my_timer, jiffies + 5);//timeout≈5*4=20ms
    return IRQ_HANDLED;
    }
    static int __init button_init(void)
    {
    int ret;
    ret = gpio_request(S5PV210_GPH2(0), "key2");
       if (ret)
       {
           printk(KERN_ERR "gpio_request Failed to register device ");
           goto error1;
       }
     
       //为新输入设备分配内存并初始化
       button_dev = input_allocate_device();
       if (!button_dev) 
       {
           printk(KERN_ERR "can't allocate input mem! ");
           goto error2;
       }
     
       button_dev->name = "gec_input";
       button_dev->id.bustype = 0x1;
       button_dev->id.product = 0x2;
       button_dev->id.vendor = 0x3;
       button_dev->id.version = 0x4;
       button_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY);//set_bit(EV_KEY,button_dev-    >evbit[BIT_WORD(EV_KEY)])
       button_dev->keybit[BIT_WORD(KEY_A)] = BIT_MASK(KEY_A);//set_bit(KEY_A, button_dev-      >keybit[BIT_WORD(KEY_A)])
       //注册一个输入设备
       ret = input_register_device(button_dev);
       if (ret) 
       {
           printk(KERN_ERR "Failed to register device ");
           goto error3;
       }
       //申请中断注册中断处理函数
       ret = request_irq(IRQ_EINT(16), button_interrupt,
       IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING | IRQF_DISABLED, "button", NULL);
       if (ret) 
       {
           printk(KERN_ERR "Can't request irq %d ", IRQ_EINT(16));
           goto error4;
       }
     
       //定时器
       init_timer(&my_timer);//初始化定时器
       my_timer.function = timer_func;//注册定时器超时处理函数
       return 0;
       error4:
       free_irq(IRQ_EINT(16), NULL);//释放分配给已定中断的内存
       input_unregister_device(button_dev);
       error3:
       input_free_device(button_dev);
       error2:
       ret = -ENOMEM;
       error1:
       gpio_free(S5PV210_GPH2(0));
     
       return ret;
    }
     
    static void __exit button_exit(void)
    {
       gpio_free(S5PV210_GPH2(0)); 
       free_irq(IRQ_EINT(16), NULL);
       input_unregister_device(button_dev);
       del_timer(&my_timer);//删除内核定时器
    }
    module_init(button_init);
    module_exit(button_exit);
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_LICENSE("GPL");
    Makefile:
    obj-m += inputk2_drv.o
    PWD ?= shell pwd
    KDIR := /opt/03.kernel_transplant/android-kernel-samsung-dev
    all:
    make -C $(KDIR) M=$(PWD) modules
    cp ./inputk2_drv.ko /mini_rootfs/modules
    cp ./inputk2_app /mini_rootfs/modules
    rm -rf ./*.o
    rm -rf ./*.order
    rm -rf ./*.symvers
    rm -rf ./*.mod.c
    rm -rf ./.*.cmd 
    rm -rf ./.*.tmp* 
    rm -rf ./.tmp_versions
     
    <键盘驱动程序>
    1. #include <linux/module.h>
    2. #include <linux/init.h>
    3. #include <linux/interrupt.h>
    4. #include <linux/platform_device.h>
    5. #include <linux/input.h>
    6. #include <linux/slab.h>
    7.  
    8. #include <mach/regs-gpio.h>
    9. #include <linux/gpio.h>
    10. #include <linux/irq.h>
    11.  
    12.  
    13. #define DHOLE2440_KBD "dhole2440kbd"
    14. #define DHOLE2440_KBD_IRQ_NUM (6)
    15. #define KBD_NONE (0xff)
    16.  
    17. #define KBD_UP (0)
    18. #define KBD_DOWN (1)
    19.  
    20. typedef struct _dhole2440_key{
    21.     unsigned int gpio;/*对应gpio口*/
    22.     unsigned int irq;/*对应中断*/
    23.     int n_key;/*键值*/
    24. }dhole2440_key;
    25.  
    26. struct dhole2440_kbd{
    27.     dhole2440_key keys[DHOLE2440_KBD_IRQ_NUM];
    28.     struct timer_list key_timer; /*按键去抖定时器*/
    29.     unsigned int key_status; /*按键状态*/
    30.     struct input_dev *input;
    31. };
    32.  
    33. struct dhole2440_kbd *p_dhole2440_kbd;
    34.  
    35.  
    36. struct dhole2440_kbd *get_kbd(void)
    37. {
    38.     printk("get_kbd p_dhole2440_kbd=%x ", (unsigned int)p_dhole2440_kbd);
    39.     return p_dhole2440_kbd;
    40. }
    41.  
    42. void set_kbd(struct dhole2440_kbd *p_kbd)
    43. {
    44.     p_dhole2440_kbd = p_kbd;
    45.  
    46.     printk("set_kbd p_kbd=%x, p_dhole2440_kbd=%x ",
    47.         (unsigned int)p_kbd, (unsigned int)p_dhole2440_kbd);
    48. }
    49.  
    50. static irqreturn_t dhole2440_kbd_handler(int irq, void *p_date)
    51. {
    52.     unsigned int n_key = 0;
    53.     struct dhole2440_kbd *p_kbd = p_date;
    54.     unsigned int key_state = 0;
    55.     int i;
    56.  
    57.     for(= 0; i < DHOLE2440_KBD_IRQ_NUM; i++)
    58.     {
    59.         if( irq == p_kbd->keys[i].irq )
    60.         {
    61.             key_state = s3c2410_gpio_getpin(p_kbd->keys[i].gpio);
    62.             n_key = p_kbd->keys[i].n_key;
    63.             break;
    64.         }
    65.     }
    66.  
    67.     printk("dhole2440_kbd_handler n_key=%d, key_state=%d ", n_key, key_state);
    68.  
    69.     input_report_key(p_kbd->input, n_key, !key_state);/*1表示按下*/
    70.     input_sync(p_kbd->input);
    71.  
    72.     return IRQ_HANDLED;
    73. }
    74.  
    75.  
    76. static void kbd_free_irqs(void)
    77. {
    78.     struct dhole2440_kbd *p_kbd = get_kbd();
    79.     int i;
    80.  
    81.     printk("kbd_free_irqs p_kbd=%x ", (unsigned int)p_kbd);
    82.    
    83.     for(= 0; i < DHOLE2440_KBD_IRQ_NUM; i++)
    84.         free_irq(p_kbd->keys[i].irq, p_kbd);
    85. }
    86.  
    87. static int kbd_req_irqs(void)
    88. {
    89.     int n_ret;
    90.     int i;
    91.     struct dhole2440_kbd *p_kbd = get_kbd();
    92.  
    93.     printk("kbd_req_irqs p_kbd=%x ", (unsigned int)p_kbd);
    94.  
    95.     for(= 0; i < DHOLE2440_KBD_IRQ_NUM; i++)
    96.     {
    97.         n_ret = request_irq(p_kbd->keys[i].irq, dhole2440_kbd_handler, IRQ_TYPE_EDGE_BOTH, DHOLE2440_KBD, p_kbd);
    98.         if(n_ret)
    99.         {
    100.             printk("%d: could not register interrupt ", p_kbd->keys[i].irq);
    101.             goto fail;
    102.         }
    103.     }
    104.  
    105.     return n_ret;
    106.  
    107. fail:
    108.     /*因为上面申请失败的那个没有成功,所以也不要释放*/
    109.     for(i--; i >= 0; i--)
    110.     {
    111.         disable_irq(p_kbd->keys[i].irq);
    112.         free_irq(p_kbd->keys[i].irq, p_kbd);
    113.     }
    114.  
    115.     return n_ret;
    116. }
    117.  
    118. static void dhole2440_init_kbd_data(struct dhole2440_kbd *p_kbd)
    119. {
    120.     printk("dhole2440_init_kbd_data p_kbd=%x ", (unsigned int)p_kbd);
    121.  
    122.     p_kbd->keys[0].gpio = S3C2410_GPG(11);
    123.     p_kbd->keys[1].gpio = S3C2410_GPG(7);
    124.     p_kbd->keys[2].gpio = S3C2410_GPG(6);
    125.     p_kbd->keys[3].gpio = S3C2410_GPG(5);
    126.     p_kbd->keys[4].gpio = S3C2410_GPG(3);
    127.     p_kbd->keys[5].gpio = S3C2410_GPG(0);
    128.  
    129.     p_kbd->keys[0].irq = IRQ_EINT19;
    130.     p_kbd->keys[1].irq = IRQ_EINT15;
    131.     p_kbd->keys[2].irq = IRQ_EINT14;
    132.     p_kbd->keys[3].irq = IRQ_EINT13;
    133.     p_kbd->keys[4].irq = IRQ_EINT11;
    134.     p_kbd->keys[5].irq = IRQ_EINT8;
    135.  
    136.     p_kbd->keys[0].n_key = KEY_0;
    137.     p_kbd->keys[1].n_key = KEY_1;
    138.     p_kbd->keys[2].n_key = KEY_2;
    139.     p_kbd->keys[3].n_key = KEY_3;
    140.     p_kbd->keys[4].n_key = KEY_ESC;
    141.     p_kbd->keys[5].n_key = KEY_ENTER;
    142. }
    143.  
    144. static int __devinit dhole2440_keys_probe(struct platform_device *pdev)
    145. {
    146.     int err = -ENOMEM;
    147.     struct dhole2440_kbd *p_dhole2440_keys = NULL;
    148.     struct input_dev *input_dev = NULL;
    149.  
    150.     printk("dhole2440_keys_probe entry! ");
    151.  
    152.     p_dhole2440_keys = kmalloc(sizeof(struct dhole2440_kbd), GFP_KERNEL);
    153.     if( !p_dhole2440_keys )
    154.     {
    155.         printk("dhole2440_keys_probe kmalloc error! ");
    156.         return err;
    157.     }
    158.     printk("dhole2440_keys_probe p_dhole2440_keys=%x ", (unsigned int)p_dhole2440_keys);
    159.  
    160.     dhole2440_init_kbd_data(p_dhole2440_keys);
    161.  
    162.     input_dev = input_allocate_device();
    163.     if (!input_dev)
    164.     {
    165.         printk("dhole2440_keys_probe input_allocate_device error! ");
    166.         goto fail;
    167.     }
    168.  
    169.     p_dhole2440_keys->input = input_dev;
    170.  
    171.     platform_set_drvdata(pdev, p_dhole2440_keys);
    172.     input_dev->name = pdev->name;
    173.     input_dev->phys = DHOLE2440_KBD"/input0";
    174.     input_dev->id.bustype = BUS_HOST;
    175.     input_dev->dev.parent = &pdev->dev;
    176.     input_dev->id.vendor = 0x0001;
    177.     input_dev->id.product = 0x0001;
    178.     input_dev->id.version = 0x0100;
    179.  
    180.     __set_bit(EV_KEY, input_dev->evbit);
    181.     __set_bit(KEY_0, input_dev->keybit);
    182.     __set_bit(KEY_1, input_dev->keybit);
    183.     __set_bit(KEY_2, input_dev->keybit);
    184.     __set_bit(KEY_3, input_dev->keybit);
    185.     __set_bit(KEY_ESC, input_dev->keybit);
    186.     __set_bit(KEY_ENTER, input_dev->keybit);
    187.     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
    188.  
    189.     err = input_register_device(input_dev);
    190.     if( err )
    191.     {
    192.         printk("dhole2440_keys_probe input_register_device error! ");
    193.         goto fail_allocate;
    194.     }
    195.  
    196.     set_kbd(p_dhole2440_keys);
    197.  
    198.     err = kbd_req_irqs();
    199.     if( err )
    200.     {
    201.         printk("dhole2440_keys_probe kbd_req_irqs error! ");
    202.         goto fail_register;
    203.     }
    204.  
    205.     printk("dhole2440_keys_probe sucess! ");
    206.  
    207.     return 0;
    208.  
    209. fail_register:
    210.     input_unregister_device(input_dev);
    211.     goto fail;
    212. fail_allocate:
    213.     input_free_device(input_dev);
    214. fail:
    215.     kfree(p_dhole2440_keys);
    216.  
    217.     return err;
    218. }
    219.  
    220. static int __devexit dhole2440_keys_remove(struct platform_device *pdev)
    221. {
    222.     struct dhole2440_kbd *p_dhole2440_keys = platform_get_drvdata(pdev);
    223.  
    224.     printk("dhole2440_keys_remove entry! ");
    225.  
    226.     kbd_free_irqs();
    227.  
    228.     input_unregister_device(p_dhole2440_keys->input);
    229.     kfree(p_dhole2440_keys);
    230.  
    231.     printk("dhole2440_keys_remove sucess! ");
    232.  
    233.     return 0;
    234. }
    235.  
    236. static void dhole2440_keys_release(struct device *dev)
    237. {
    238.     dev = dev;
    239. }
    240.  
    241.  
    242. static struct platform_driver dhole2440_keys_device_driver = {
    243.     .probe = dhole2440_keys_probe,
    244.     .remove = __devexit_p(dhole2440_keys_remove),
    245.     .driver = {
    246.         .name = DHOLE2440_KBD,
    247.         .owner = THIS_MODULE,
    248.     }
    249. };
    250.  
    251. static struct platform_device dhole2440_device_kbd = {
    252.     .name = DHOLE2440_KBD,
    253.     .id = -1,
    254.     .dev = {
    255.         .release = dhole2440_keys_release,
    256.     }
    257. };
    258.  
    259. static int __init dhole2440_keys_init(void)
    260. {
    261.     int n_ret;
    262.     n_ret = platform_driver_register(&dhole2440_keys_device_driver);
    263.  
    264.     printk("dhole2440_keys_init 1 n_ret=%d jiffies=%lu,HZ=%d ", n_ret, jiffies, HZ);
    265.     if( n_ret )
    266.         return n_ret;
    267.  
    268.     n_ret = platform_device_register(&dhole2440_device_kbd);
    269.  
    270.     printk("dhole2440_keys_init 2 n_ret=%d ", n_ret);
    271.     if( n_ret )
    272.         goto fail;
    273.  
    274.     return n_ret;
    275.  
    276. fail:
    277.     platform_driver_unregister(&dhole2440_keys_device_driver);
    278.  
    279.     return n_ret;
    280. }
    281.  
    282. static void __exit dhole2440_keys_exit(void)
    283. {
    284.     printk("dhole2440_keys_exit ");
    285.  
    286.     platform_device_unregister(&dhole2440_device_kbd);
    287.  
    288.     platform_driver_unregister(&dhole2440_keys_device_driver);
    289. }
    290.  
    291. module_init(dhole2440_keys_init);
    292. module_exit(dhole2440_keys_exit);
    293.  
    294. MODULE_DESCRIPTION("dhole2440 keyboard input events driver");
    295. MODULE_AUTHOR("liuzhiping <lyliuzhiping@yeah.net style="word-wrap: break-word;">");
    296. MODULE_LICENSE("GPL");
    297. MODULE_ALIAS("platform:dhole2440 keyboard driver");
     

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

  • 相关阅读:
    CodeForces Round #516 Div2 题解
    BZOJ3300: [USACO2011 Feb]Best Parenthesis 模拟
    BZOJ4994: [Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组
    BZOJ3297: [USACO2011 Open]forgot DP+字符串
    BZOJ3296: [USACO2011 Open] Learning Languages 并查集
    BZOJ2442: [Usaco2011 Open]修剪草坪 单调队列优化dp
    BZOJ3298: [USACO 2011Open]cow checkers 威佐夫博弈
    什么是 DDoS 攻击?
    快速了解“云原生”(Cloud Native)和前端开发的技术结合点
    一文读懂spring boot 和微服务的关系
  • 原文地址:https://www.cnblogs.com/big-devil/p/8590073.html
Copyright © 2020-2023  润新知