Linux input子系统实例分析(一)

这是一个简单的输入设备驱动实例。这个输入设备只有一个按键,按键被连接到一条中断线上,当按键被按下时,将产生一个中断,内核将检测到这个中断,并对其进行处理。该实例的代码如下:
 
 
   1:  #include <linux/module.h>
   2:  #include <linux/init.h>
   3:  #include <linux/fs.h>
   4:  #include <linux/interrupt.h>
   5:  #include <linux/irq.h>
   6:  #include <linux/sched.h>
   7:  #include <linux/spinlock.h>
   8:  #include <linux/pm.h>
   9:  #include <linux/slab.h>
  10:  #include <linux/sysctl.h>
  11:  #include <linux/proc_fs.h>
  12:  #include <linux/delay.h>
  13:  #include <linux/platform_device.h>
  14:  #include <linux/input.h>
  15:  #include <linux/workqueue.h>
  16:  #include <linux/gpio.h>
  17:   
  18:   
  19:  #define gpio_key        32*4+30 //PD(30) 即将使用的gpio
  20:  #define DEV_NAME         "gpio_key"
  21:   
  22:  int g_irq = -1;                    //中断号
  23:  static struct input_dev *button_dev;  //输入子系统设备结构
  24:   
  25:   
  26:  //中断处理函数
  27:  static irqreturn_t button_interrupt(int irq, void *p)
  28:  {
  29:      /*get pin value <down 0, up 1> */
  30:   
  31:      int val = gpio_get_value(gpio_key);
  32:   
  33:      input_report_key(button_dev, KEY_1, val);
  34:   
  35:      input_sync(button_dev);
  36:   
  37:      return IRQ_RETVAL(IRQ_HANDLED);
  38:  }
  39:   
  40:   
  41:   
  42:  static int __init button_init(void)
  43:  {
  44:      int irq = -1, err = -1;
  45:      unsigned long irqflags;
  46:      //申请gpio
  47:      err = gpio_request(gpio_key, "test_key");
  48:      if(err < 0){
  49:          printk("request gpio[%d] failed...
", gpio_key);
  50:          goto end1;
  51:      }
  52:      
  53:      //gpio输入
  54:      err = gpio_direction_input(gpio_key);
  55:      if (err < 0) {
  56:          //dev_err(dev, "failed to configure"
  57:          //    " direction for GPIO %d, error %d
",
  58:          //    gpio_key, error);
  59:          goto end2;
  60:      }
  61:      //申请gpio中断号
  62:      g_irq = (irq = gpio_to_irq(gpio_key));
  63:      if (irq < 0) {
  64:          err = irq;
  65:          //dev_err(dev, "Unable to get irq number for GPIO %d, error %d
",
  66:          //    gpio_key, irq);
  67:          goto end2;
  68:      }
  69:      //中断类型
  70:      irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
  71:      /* 申请中断 */
  72:      if (request_irq(irq, button_interrupt, irqflags, DEV_NAME, NULL)) {
  73:   
  74:          printk(KERN_ERR"cannotallocate irq");
  75:          err= -EBUSY;
  76:          goto end2;
  77:      }
  78:   
  79:      /*分配input_dev */
  80:      button_dev = input_allocate_device();
  81:      if (button_dev == NULL) {
  82:          printk(KERN_ERR "notenough memory
");
  83:          err= - ENOMEM;
  84:          goto end3;
  85:   
  86:      }
  87:      /*设置输入设备支持的事件类型和事件代码 */
  88:      button_dev->name = "key_gpio";
  89:      set_bit(EV_KEY, button_dev->evbit);
  90:      set_bit(KEY_1, button_dev->keybit);
  91:      
  92:      /*把输入设备注册进核心层 */
  93:      err = input_register_device(button_dev);
  94:      if(err) {
  95:          printk(KERN_ERR "failedto register device
");
  96:          goto end4;
  97:      }
  98:   
  99:      printk("initialized
");
 100:      return 0;
 101:   
 102:  end4:
 103:      input_free_device(button_dev);
 104:  end3:
 105:      free_irq(irq, NULL);
 106:  end2:
 107:      gpio_free(gpio_key);
 108:  end1:
 109:      return err;
 110:   
 111:  }
 112:   
 113:   
 114:   
 115:  static void __exit button_exit(void)
 116:  {
 117:      input_unregister_device(button_dev);
 118:       input_free_device(button_dev);
 119:   
 120:      gpio_free(gpio_key);
 121:      free_irq(g_irq, NULL);
 122:  }
 123:   
 124:   
 125:   
 126:  module_init(button_init);
 127:  module_exit(button_exit);
 128:   
 129:  MODULE_LICENSE("GPL");
 130:  MODULE_AUTHOR("xuyonghong@duotin.com>");
 131:   
 132:   
 133:   
 134:   
 135:   
 136:   
 
当编译进内核烧写板子后可以看到相应的设备文件:

root@CarRadio:/sys/devices# ls virtual/input/input2/
capabilities  id            name          power         subsystem     uniq
event2        modalias      phys          properties    uevent
root@CarRadio:/sys/devices# cat virtual/input/input2/name
key_gpio
root@CarRadio:/sys/devices#

这样就可以监控event2来捕捉按键

root@CarRadio:/# ls dev/input/event2
dev/input/event2
root@CarRadio:/#

 

驱动分析:

1.申请gpio

gpio_request(gpio_key, "test_key");

2.设置为gpio输入模式

gpio_direction_input(gpio_key);

3.申请gpio中断号,注册中断

//申请gpio中断号 g_irq = (irq = gpio_to_irq(gpio_key));

/* 申请中断 */
request_irq(irq, button_interrupt, irqflags, DEV_NAME, NULL);

4.分配input_dev设备

/*分配input_dev */
button_dev = input_allocate_device();

5.把输入设备注册进核心层

input_register_device(button_dev);

 

 

原文地址:https://www.cnblogs.com/xuyh/p/4989077.html