Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1242429
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: LINUX

2015-06-16 10:30:30

  这两种情况,内核中都有考虑,都在drivers/input/keyboard/ 下面。

GPIO 独立按键是 gpio_keys.c

GPIO 矩阵键盘是 matrix_keypad.c

具体也没有什么好分析的,主要就是采用platform 方式注册input 子系统,往应用层报键值。

在此基础上,添加相关的驱动,格式很固有化。直接上自己整理的模板吧。

GPIO 独立按键

点击(此处)折叠或打开

  1. #define SABRESD_VOLUME_UP    IMX_GPIO_NR(1, 4) //得到gpio number 号
  2. #define SABRESD_VOLUME_DN    IMX_GPIO_NR(1, 5)

  3. //定义宏
  4. #ifdefined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
  5. #define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake, debounce)    \
  6. {                                \
  7.     .gpio        = gpio_num,                \
  8.     .type        = EV_KEY,                \
  9.     .code        = ev_code,                \
  10.     .active_low    = act_low,                \
  11.     .desc        = "btn " descr,                \
  12.     .wakeup        = wake,                    \
  13.     .debounce_interval = debounce,                \
  14. }
  15. //上面宏定义的数组
  16. static struct gpio_keys_button CPU_NAME_buttons[] = {
  17.     GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1),
  18.     GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_VOLUMEDOWN, 1, "volume-down", 0, 1),
  19.     GPIO_BUTTON(SABRESD_POWER_OFF, KEY_POWER, 1, "power", 1, 1),
  20. };

  21. static struct gpio_keys_platform_data CPU_NAME_button_data = {
  22.     .buttons    = CPU_NAME_buttons,
  23.     .nbuttons    = ARRAY_SIZE(CPU_NAME_buttons),
  24. };
  25. //platform device 与driver 中对应的
  26. static struct platform_device CPU_NAME_button_device = {
  27.     .name        = "gpio-keys",
  28.     .id        = -1,
  29.     .num_resources = 0,
  30.     .dev        = {
  31.         .platform_data = &CPU_NAME_button_data,
  32.     }
  33. };
  34. //注册设备的函数
  35. static void __init CPU_NAME_add_device_buttons(void)
  36. {
  37.     platform_device_register(&CPU_NAME_button_device);
  38. }
  39. #else
  40. static void __init CPU_NAME_add_device_buttons(void) {}
  41. #endif

    有些时候因不同CPU BSP GPIO 封装,在driver 中会出现一些问题。比如 gpio_request   可能会重复(imx287
得到
GPIO号的时候就已经request ,TMD超前了)  如下这段代码要屏蔽。

点击(此处)折叠或打开

  1. #if 0
  2.                 error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
  3.                 if (error < 0) {
  4.                         pr_err("gpio-keys: failed to request GPIO %d,"
  5.                                 " error %d\n", button->gpio, error);
  6.                         goto fail2;
  7.                 }
  8. #endif

GPIO 矩阵键盘


点击(此处)折叠或打开

  1. #if 1
  2. /*
  3.  * Tosa Keyboard
  4.  */
  5.  #include <linux/input/matrix_keypad.h>
  6. //矩阵键盘按下时对应的键码表
  7. static const uint32_t tosakbd_keymap[] = {
  8.     KEY(0, 0, KEY_1),
  9.     KEY(0, 1, KEY_2),
  10.     KEY(0, 2, KEY_3),


  11.     KEY(1, 0, KEY_4),
  12.     KEY(1, 1, KEY_5),
  13.     KEY(1, 2, KEY_6),


  14.     KEY(2, 0, KEY_7),
  15.     KEY(2, 1, KEY_8),
  16.     KEY(2, 2, KEY_9),


  17.     KEY(3, 0, KEY_UP),
  18.     KEY(3, 1, KEY_0),
  19.     KEY(3, 2, KEY_DOWN),

  20.     KEY(4, 0, KEY_BACK),
  21.     KEY(4, 1, KEY_ENTER),
  22.     KEY(4, 2, KEY_ESC),
  23.     

  24. };

  25. static struct matrix_keymap_data tosakbd_keymap_data = {
  26.     .keymap        = tosakbd_keymap,
  27.     .keymap_size    = ARRAY_SIZE(tosakbd_keymap),
  28. };

  29. //列选 得到GPIO 口number 号
  30. static const int tosakbd_col_gpios[] =
  31.             {
  32.                 // MXS_PIN_TO_GPIO( PINID_SSP0_DATA5), // 4
  33.                 MXS_PIN_TO_GPIO(PINID_LCD_D08), // 5
  34.                 MXS_PIN_TO_GPIO(PINID_LCD_D09), // 6
  35.                 MXS_PIN_TO_GPIO(PINID_LCD_D10) // 7
  36.             };
  37. //行选 得到GPIO 口number 号            
  38. static const int tosakbd_row_gpios[] =
  39.             {
  40.                 MXS_PIN_TO_GPIO(PINID_LCD_D11), // 2
  41.                 MXS_PIN_TO_GPIO(PINID_LCD_D12), // 2
  42.                 MXS_PIN_TO_GPIO(PINID_LCD_D13), // 3
  43.                 MXS_PIN_TO_GPIO(PINID_LCD_D14),              // 1
  44.                 MXS_PIN_TO_GPIO(PINID_LCD_D15) // 0
  45.             };
  46. //driver 中的需要的data
  47. static struct matrix_keypad_platform_data CPU_NAMEkbd_pdata = {
  48.     .keymap_data        = &tosakbd_keymap_data,
  49.     .row_gpios        = tosakbd_row_gpios,
  50.     .col_gpios        = tosakbd_col_gpios,
  51.     .num_row_gpios        = ARRAY_SIZE(tosakbd_row_gpios),
  52.     .num_col_gpios        = ARRAY_SIZE(tosakbd_col_gpios),
  53.     .col_scan_delay_us    = 10,
  54.     .debounce_ms        = 10,
  55.     .wakeup            = 1,

  56.     .active_low =0 ,
  57. };

  58. static struct platform_device CPU_NAMEkbd_device = {
  59.     .name        = "matrix-keypad",
  60.     .id        = -1,
  61.     .dev        = {
  62.         .platform_data = &CPU_NAMEkbd_pdata,
  63.     },
  64. };

  65. #endif

 上面的两种方式,有些时候因不同CPU BSP GPIO 封装,在driver 中会出现一些问题。由于不同CPU GPIO口
产生中断的触发方式不同,
这里出现问题的更多。

点击(此处)折叠或打开

  1. err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
  2.                 matrix_keypad_interrupt,
  3.                 IRQF_DISABLED |
  4.                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  5.                 "matrix-keypad", keypad);


  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING   很多CPU无法同时支持上升延与下降延触发。只能选择其中一个,要么FALLING ,要么RISING
 这两种方式,内核都已经封装成足够简单的方式了,用不着自己去写一个驱动,类似于填空就好了。







阅读(9095) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~