zoukankan      html  css  js  c++  java
  • Linux input子系统实例分析(二)

    紧接着上一节的实例我们来分析调用的input子系统的接口:

    1. input_dev,用来标识输入设备

       1:  struct input_dev {
       2:      const char *name;      //设备名
       3:      const char *phys;     // 设备在系统中路径
       4:      const char *uniq;
       5:      struct input_id id;    //与input_handler匹配用的id
       6:   
       7:      unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
       8:   
       9:      unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //设备所支持事件类型,主要有EV_SYNC,EV_KEY,EV_REL,EV_ABS等       
      10:      unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];// 按键所对应的位图
      11:      unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//  相对坐标对应位图
      12:      unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];// 绝对坐标对应位图
      13:      unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//支持其它事件
      14:      unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//支持led事件
      15:      unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//支持声音事件
      16:      unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//支持受力事件
      17:      unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//支持开关机事件
      18:   
      19:      unsigned int hint_events_per_packet;
      20:   
      21:      unsigned int keycodemax;
      22:      unsigned int keycodesize;
      23:      void *keycode;
      24:   
      25:      int (*setkeycode)(struct input_dev *dev,
      26:                const struct input_keymap_entry *ke,
      27:                unsigned int *old_keycode);
      28:      int (*getkeycode)(struct input_dev *dev,
      29:                struct input_keymap_entry *ke);
      30:   
      31:      struct ff_device *ff;
      32:   
      33:      unsigned int repeat_key;//最近一次的按键值
      34:      struct timer_list timer;
      35:   
      36:      int rep[REP_CNT];
      37:   
      38:      struct input_mt_slot *mt;
      39:      int mtsize;
      40:      int slot;
      41:      int trkid;
      42:   
      43:      struct input_absinfo *absinfo;
      44:   
      45:      unsigned long key[BITS_TO_LONGS(KEY_CNT)];//反应设备当前的按键状态
      46:      unsigned long led[BITS_TO_LONGS(LED_CNT)];//反应设备当前的led状态
      47:      unsigned long snd[BITS_TO_LONGS(SND_CNT)];//反应设备当前的声音输入状态
      48:      unsigned long sw[BITS_TO_LONGS(SW_CNT)];//反应设备当前的开关状态
      49:   
      50:      int (*open)(struct input_dev *dev);//第一次打开设备时调用,初始化设备用
      51:      void (*close)(struct input_dev *dev);//最后一个应用程序释放设备时用,关闭设备
      52:      int (*flush)(struct input_dev *dev, struct file *file);/*用于处理传递给设备的事件,如LED事件和声音事件*/
      53:      //  事件处理函数,主要是接收用户下发的命令,如点亮led;
      54:      int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
      55:   
      56:      struct input_handle __rcu *grab;    //当前占有该设备的input_handle
      57:   
      58:      spinlock_t event_lock;
      59:      struct mutex mutex;
      60:   
      61:      unsigned int users;        //打开该设备的用户数量(input handlers)
      62:      bool going_away;
      63:   
      64:      bool sync;
      65:   
      66:      struct device dev;
      67:   
      68:      struct list_head    h_list; // 设备所支持的input handle; 
      69:      struct list_head    node;    //用于将此input_dev链接到input_dev_list
      70:  };

    2.把输入设备注册进核心层  int input_register_device(struct input_dev *dev)

       1:  int input_register_device(struct input_dev *dev)
       2:  {
       3:      static atomic_t input_no = ATOMIC_INIT(0);
       4:      struct input_handler *handler;
       5:      const char *path;
       6:      int error;
       7:   
       8:      /* Every input device generates EV_SYN/SYN_REPORT events. */
       9:      __set_bit(EV_SYN, dev->evbit);//  /*表示设备支持所有的事件*/ 
      10:   
      11:      /* KEY_RESERVED is not supposed to be transmitted to userspace. */
      12:      __clear_bit(KEY_RESERVED, dev->keybit);
      13:   
      14:      /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
      15:      input_cleanse_bitmasks(dev);
      16:   
      17:      if (!dev->hint_events_per_packet)
      18:          dev->hint_events_per_packet =
      19:                  input_estimate_events_per_packet(dev);
      20:   
      21:      /*
      22:       * If delay and period are pre-set by the driver, then autorepeating
      23:       * is handled by the driver itself and we don't do it in input.c.
      24:       */
      25:      init_timer(&dev->timer);//初始化定时器
      26:      /*如果dev->rep[REP_DELAY]和dev->rep[REP_PERIOD]没有设值,
      27:      则将其赋默认值,这主要是为自动处理重复按键定义*/
      28:      if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
      29:          dev->timer.data = (long) dev;
      30:          dev->timer.function = input_repeat_key;//定时器处理函数
      31:          dev->rep[REP_DELAY] = 250;
      32:          dev->rep[REP_PERIOD] = 33;
      33:      }
      34:   
      35:      if (!dev->getkeycode)//获取键值
      36:          dev->getkeycode = input_default_getkeycode;
      37:   
      38:      if (!dev->setkeycode)//设置键值
      39:          dev->setkeycode = input_default_setkeycode;
      40:      //设置input_dev中的device的名字
      41:      dev_set_name(&dev->dev, "input%ld",
      42:               (unsigned long) atomic_inc_return(&input_no) - 1);
      43:   
      44:      error = device_add(&dev->dev);//将input_dev包含的device结构注册到Linux设备模型中,并可以在sysfs文件系统中表现出来。
      45:      if (error)
      46:          return error;
      47:   
      48:      path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
      49:      pr_info("%s as %s
    ",
      50:          dev->name ? dev->name : "Unspecified device",
      51:          path ? path : "N/A");
      52:      kfree(path);
      53:   
      54:      error = mutex_lock_interruptible(&input_mutex);
      55:      if (error) {
      56:          device_del(&dev->dev);
      57:          return error;
      58:      }
      59:   
      60:      list_add_tail(&dev->node, &input_dev_list);//添加到input device 链表
      61:   
      62:      list_for_each_entry(handler, &input_handler_list, node)//
      63:          input_attach_handler(dev, handler);
      64:   
      65:      input_wakeup_procfs_readers();
      66:   
      67:      mutex_unlock(&input_mutex);
      68:   
      69:      return 0;

     

    3.调用input_report_key函数报告此事件

       1:  static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
       2:  {
       3:      input_event(dev, EV_KEY, code, !!value);
       4:  }

    input_report_key函数参数,1.input_dev设备,2。按键值 3.按键的状态(1按下,0松开)

    在input.h中定义了按键类code的值,BTN_0,BTN_1,KEY_A KEY_B等等这样的键值

    此函数只是调用了input_event函数,这个函数是总的事件报告函数,

       1:  void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
       2:  {
       3:      unsigned long flags;
       4:   
       5:      if (is_event_supported(type, dev->evbit, EV_MAX)) {    //(1)
       6:   
       7:          spin_lock_irqsave(&dev->event_lock, flags);    //(2)
       8:          add_input_randomness(type, code, value);    //(3)
       9:          input_handle_event(dev, type, code, value);    //(4)
      10:          spin_unlock_irqrestore(&dev->event_lock, flags);//(5)    
      11:      }
      12:  }

    参数1.input_dev 2.事件类型(如EV_KEY键盘事件) 3.此类型具体事件code(如KEY_A,键A) 4.此事件的值(如1,按键按下)

    (1)设备是否支持该事件类型。下面分析

    (2)自旋锁上锁

    (3)因为按键是随机事件,所以对随机熵有贡献,对于驱动无关。具体不懂

    (4)进一步处理报告的事件

    (5)自旋锁解锁

     
     
     
  • 相关阅读:
    Java: 数据类型
    数据结构是什么
    数据结构:进制转换
    数据结构:堆与栈
    class的写法
    Java:异常体系
    数据结构: 先进后出——堆栈
    tomcat:web容器
    Windows: Dos命令
    面向函数范式编程
  • 原文地址:https://www.cnblogs.com/xuyh/p/4991449.html
Copyright © 2011-2022 走看看