1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include <linux/fs.h>
    4. #include <linux/kernel.h>
    5. #include <asm/io.h>
    6. #include <asm/uaccess.h>
    7. #include <linux/device.h>
    8. #include <linux/gpio.h>
    9. #include <linux/irq.h>
    10. #include <linux/interrupt.h>
    11. #include <linux/poll.h>
    12. #include <asm-generic/errno-base.h>
    13. #include <linux/input.h>
    14. #include <linux/of_irq.h>
    15. //描述按键信息的数据结构
    16. struct key_resource {
    17. char *name;
    18. int irq;
    19. int gpio;
    20. int code;
    21. };
    22. //保存按键的硬件信息,全局化
    23. static struct key_resource *pKeyData = NULL;
    24. //定义一个按键去抖动的定时器
    25. static struct timer_list key_timer;
    26. //新建一个输入子系统的设备结构
    27. static struct input_dev *keys_input;
    28. //定义初始化按键硬件信息的对象
    29. static struct key_resource key_info[] = {
    30. {
    31. .name = "KEY_ENTER",
    32. //.irq = IRQ_EXT0,
    33. .gpio = NUC970_PG14,
    34. .code = KEY_ENTER
    35. },
    36. {
    37. .name = "KEY_CANCEL",
    38. //.irq = IRQ_EXT0,
    39. .gpio = NUC970_PG13,
    40. .code = KEY_CANCEL
    41. },
    42. {
    43. .name = "KEY_UP",
    44. //.irq = IRQ_EXT0,
    45. .gpio = NUC970_PG12,
    46. .code = KEY_UP
    47. },
    48. {
    49. .name = "KEY_DOWN",
    50. //.irq = IRQ_EXT0,
    51. .gpio = NUC970_PG11,
    52. .code = KEY_DOWN
    53. },
    54. };
    55. //中断处理函数
    56. static irqreturn_t key_isr(int irq, void *dev)
    57. {
    58. //获取按键信息
    59. pKeyData = (struct key_resource *)dev;
    60. //启动定时器
    61. mod_timer(&key_timer, msecs_to_jiffies(10));
    62. return IRQ_HANDLED;
    63. }
    64. //定时器的超时处理函数
    65. static void key_timer_function(unsigned long data)
    66. {
    67. unsigned int pin_val;
    68. if (NULL == pKeyData) {
    69. return;
    70. } else {
    71. printk("key:%s\n", pKeyData->name);
    72. pin_val = gpio_get_value(pKeyData->gpio);
    73. if (!pin_val) {
    74. input_event(keys_input, EV_KEY, pKeyData->code, 0);
    75. input_sync(keys_input);
    76. }
    77. }
    78. }
    79. static int key_init(void)
    80. {
    81. int i,ret,irqno, cnt;
    82. //分配一个keys_input结构体
    83. keys_input = input_allocate_device();
    84. if (!keys_input)
    85. {
    86. printk("%s %s LINE: %d alloc input failed!!!\n",__FILE__, __FUNCTION__, __LINE__);
    87. return -ENOMEM;
    88. }
    89. //设置输入事件类型
    90. set_bit(EV_KEY, keys_input->evbit);
    91. set_bit(EV_REP, keys_input->evbit);
    92. //输入事件类型的哪一种
    93. set_bit(KEY_ENTER, keys_input->keybit);
    94. set_bit(KEY_CANCEL, keys_input->keybit);
    95. set_bit(KEY_UP, keys_input->keybit);
    96. set_bit(KEY_DOWN, keys_input->keybit);
    97. //注册
    98. ret = input_register_device(keys_input);
    99. if (ret) {
    100. printk("%s %s LINE:%d failed to register input device\n",__FILE__, __FUNCTION__, __LINE__);
    101. return -1;
    102. }
    103. cnt = 0;
    104. for (i=0; i < ARRAY_SIZE(key_info); i++) {
    105. ret = gpio_request(key_info[i].gpio, key_info[i].name);
    106. if (ret) {
    107. printk("Request GPIO = %d failed, ret = %d\n", key_info[i].gpio, ret);
    108. goto fail;
    109. }
    110. irqno = gpio_to_irq(key_info[i].gpio);
    111. key_info[i].irq = irqno;
    112. ret = request_irq(key_info[i].irq, key_isr, IRQF_TRIGGER_FALLING,
    113. key_info[i].name, &key_info[i]);
    114. if (ret) {
    115. printk("GPIO = %d, request irq failed, ret = %d\n", key_info[i].gpio, ret);
    116. goto fail;
    117. }
    118. cnt++;
    119. }
    120. init_timer(&key_timer);
    121. key_timer.function = key_timer_function;
    122. printk("Add ZKS Key SUCCESSS!!!");
    123. return 0;
    124. fail:
    125. input_free_device(keys_input);
    126. for (i =0; i < cnt; i++) {
    127. gpio_free(key_info[i].gpio);
    128. free_irq(key_info[i].irq, &key_info[i]);
    129. }
    130. return ret;
    131. }
    132. static void key_exit(void)
    133. {
    134. int i;
    135. input_free_device(keys_input);
    136. for (i = 0; i < ARRAY_SIZE(key_info); i++) {
    137. gpio_free(key_info[i].gpio);
    138. free_irq(key_info[i].irq, &key_info[i]);
    139. }
    140. }
    141. module_init(key_init);
    142. module_exit(key_exit);
    143. MODULE_LICENSE("GPL");