Cross-Referenced Linuxand Device DriverCode
[ source navigation ] [diffmarkup ] [ identifiersearch ] [ freetextsearch ] [ filesearch ] |
Version: [ 2.6.11.8 ][ 2.6.25 ][ 2.6.25.8 ][ 2.6.31.13 ] Architecture:[ i386 ]
1 /* 2 * GPIO driven matrix keyboard driver 3 * 4 * Copyright (c) 2008 Marek Vasut <[email protected]> 5 * 6 * Based on corgikbd.c 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14 #include <linux/types.h> 15 #include <linux/delay.h> 16 #include <linux/platform_device.h> 17 #include <linux/init.h> 18 #include <linux/input.h> 19 #include <linux/irq.h> 20 #include <linux/interrupt.h> 21 #include <linux/jiffies.h> 22 #include <linux/module.h> 23 #include <linux/gpio.h> 24 #include <linux/input/matrix_keypad.h> 25 26 struct matrix_keypad { 27 const struct matrix_keypad_platform_data *pdata; 28 struct input_dev *input_dev; 29 unsigned short *keycodes; 30 unsigned int row_shift; 31 32 uint32_t last_key_state[MATRIX_MAX_COLS]; 33 struct delayed_work work; 34 bool scan_pending; 35 bool stopped; 36 spinlock_t lock; 37 }; 38 39 /* 40 * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause 41 * minmal side effect when scanning other columns, here it is configured to 42 * be input, and it should work on most platforms. 43 */ 44 static void __activate_col(const struct matrix_keypad_platform_data *pdata, 45 int col, bool on) 46 { 47 bool level_on = !pdata->active_low; 48 49 if (on) { 50 gpio_direction_output(pdata->col_gpios[col], level_on); 51 } else { 52 gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); 53 gpio_direction_input(pdata->col_gpios[col]); 54 } 55 } 56 57 static void activate_col(const struct matrix_keypad_platform_data *pdata, 58 int col, bool on) 59 { 60 __activate_col(pdata, col, on); 61 62 if (on && pdata->col_scan_delay_us) 63 udelay(pdata->col_scan_delay_us); 64 } 65 66 static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, 67 bool on) 68 { 69 int col; 70 71 for (col = 0; col < pdata->num_col_gpios; col++) 72 __activate_col(pdata, col, on); 73 } 74 75 static bool row_asserted(const struct matrix_keypad_platform_data *pdata, 76 int row) 77 { 78 return gpio_get_value_cansleep(pdata->row_gpios[row]) ? 79 !pdata->active_low : pdata->active_low; 80 } 81 82 static void enable_row_irqs(struct matrix_keypad *keypad) 83 { 84 const struct matrix_keypad_platform_data *pdata = keypad->pdata; 85 int i; 86 87 for (i = 0; i < pdata->num_row_gpios; i++) //使能中断。 88 enable_irq(gpio_to_irq(pdata->row_gpios[i])); 89 } 90 91 static void disable_row_irqs(struct matrix_keypad *keypad) 92 { 93 const struct matrix_keypad_platform_data *pdata = keypad->pdata; 94 int i; 95 96 for (i = 0; i < pdata->num_row_gpios; i++) 这个是关中断,记得以前使用disable_irq()时有时候会出错。 所以使用disable_irq_nosync()会更好友好一些。 97 disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); 98 } 99 使用input子系统的一般流程为: input_allocate_device()申请一个input_dev设备――> 初始化该input_dev――> input_register_device()向子系统注册该设备――> 中断时input_event()向子系 统报告事件。 100 /* 101 * This gets the keys from keyboard and reports it to input subsystem 102 */ 这就是延后的工作的函数体,依次进行列行扫描来判断哪个按键被按下,然后使用report_key()向 input core提交按键事件。