Iput子系统探究--1(input_dev)



1.input子系统初始化

input子系统对上层应用提供一个统一的接口--字符设备接口-主设备号13

static const struct file_operations input_fops = {
 .owner = THIS_MODULE,
 .open = input_open_file,
 .llseek = noop_llseek,
};

static int __init input_init(void)
{
 int err;

 err = class_register(&input_class); /*注册input设备类*/

 err = input_proc_init();   /*初始化input_proc*/
 

 err = register_chrdev(INPUT_MAJOR, "input", &input_fops);/*注册input字符设备*/
 
}


2.关于input设备
2.1 设备的数据结构
 
/**
 * struct input_dev - represents an input device
 * @name: name of the device
 * @id: id of the device (struct input_id)
 
 * @evbit: bitmap of types of events supported by the device (EV_KEY,
 * EV_REL, etc.)
 * @keybit: bitmap of keys/buttons this device has
 * @relbit: bitmap of relative axes for the device
 * @absbit: bitmap of absolute axes for the device
 * @mscbit: bitmap of miscellaneous events supported by the device
 * @ledbit: bitmap of leds present on the device
 * @sndbit: bitmap of sound effects supported by the device
 * @ffbit: bitmap of force feedback effects supported by the device
 * @swbit: bitmap of switches present on the device

 * @keycodemax: size of keycode table
 * @keycodesize: size of elements in keycode table
 * @keycode: map of scancodes to keycodes for this device
 * @getkeycode: optional legacy method to retrieve current keymap.
 * @setkeycode: optional method to alter current keymap, used to implement
 * sparse keymaps. If not supplied default mechanism will be used.
 * The method is being called while holding event_lock and thus must
 * not sleep
 * @getkeycode_new: transition method
 * @setkeycode_new: transition method
 
 * @repeat_key: stores key code of the last key pressed; used to implement
 * software autorepeat
 * @open: this method is called when the very first user calls
 * input_open_device(). The driver must prepare the device
 * to start generating events (start polling thread,
 * request an IRQ, submit URB, etc.)
 *
 * @event: event handler for events sent _to_ the device, like EV_LED
 * or EV_SND. The device is expected to carry out the requested
 * action (turn on a LED, play sound, etc.) The call is protected
 * by @event_lock and must not sleep
 
 * @grab: input handle that currently has the device grabbed (via
 * EVIOCGRAB ioctl). When a handle grabs a device it becomes sole
 * recipient for all input events coming from the device
 
 * @event_lock: this spinlock is is taken when input core receives
 * and processes a new event for the device (in input_event()).
 * Code that accesses and/or modifies parameters of a device
 * (such as keymap or absmin, absmax, absfuzz, etc.) after device
 * has been registered with input core must take this lock.
 
 * @mutex: serializes calls to open(), close() and flush() methods-->互斥访问
 
 * @sync: set to %true when there were no new events since last EV_SYN
 * @dev: driver model's view of this device
 * @h_list: list of input handles associated with the device. When
 * accessing the list dev->mutex must be held
 * @node: used to place the device onto input_dev_list
 */
 
//#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))  -->nr/ 32
struct input_dev {
 const char *name;
 struct input_id id;

 unsigned long evbit[BITS_TO_LONGS(EV_CNT)];     //evbit[1]; -->事件类型
 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];   //keybit[24];-->按键
 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; //relbie[1] 
 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; 
 unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
 unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
 unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
 unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
 unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

 unsigned int keycodemax;
 unsigned int keycodesize;
 void *keycode;

 int (*setkeycode)(struct input_dev *dev,
     unsigned int scancode, unsigned int keycode);
 int (*getkeycode)(struct input_dev *dev,
     unsigned int scancode, unsigned int *keycode);
 int (*setkeycode_new)(struct input_dev *dev,
         const struct input_keymap_entry *ke,
         unsigned int *old_keycode);
 int (*getkeycode_new)(struct input_dev *dev,
         struct input_keymap_entry *ke);


 unsigned int repeat_key;
 struct timer_list timer;

 int rep[REP_CNT];

 
 unsigned long key[BITS_TO_LONGS(KEY_CNT)];
 unsigned long led[BITS_TO_LONGS(LED_CNT)];
 unsigned long snd[BITS_TO_LONGS(SND_CNT)];
 unsigned long sw[BITS_TO_LONGS(SW_CNT)];

 int (*open)(struct input_dev *dev);
 void (*close)(struct input_dev *dev);
 int (*flush)(struct input_dev *dev, struct file *file);
 int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

 struct input_handle __rcu *grab;

 spinlock_t event_lock;
 struct mutex mutex;

 bool sync;

 struct device dev;

 /*h_list: list of input handles associated with the device*/
 struct list_head h_list;
 
 /*node: used to place the device onto input_dev_list*/
 struct list_head node;
};
2.2 分配设备-->
struct input_dev *input_allocate_device(void)
{
 struct input_dev *dev;

 dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 
 if (dev) {
  
  dev->dev.type = &input_dev_type;  /*设置device_type*/
  
  dev->dev.class = &input_class;   /*设置设备类*/
  
  device_initialize(&dev->dev);   /*初始化设备*/
   
  mutex_init(&dev->mutex);    /*初始化mutex*/
  
  spin_lock_init(&dev->event_lock);  /*初始化自旋锁*/
  
  /*h_list: list of input handles associated with the device*/
  INIT_LIST_HEAD(&dev->h_list);   
  
  /*node: used to place the device onto input_dev_list*/
  INIT_LIST_HEAD(&dev->node);    

  __module_get(THIS_MODULE);
 }

 return dev;
}

2.3 注册设备
{
 static atomic_t input_no = ATOMIC_INIT(0);
 struct input_handler *handler;
 const char *path;
 int error;

 /* Every input device generates EV_SYN/SYN_REPORT events. */
 __set_bit(EV_SYN, dev->evbit);

 /* KEY_RESERVED is not supposed to be transmitted to userspace. */
 __clear_bit(KEY_RESERVED, dev->keybit);


 /*
  * If delay and period are pre-set by the driver, then autorepeating
  * is handled by the driver itself and we don't do it in input.c.
  */
 init_timer(&dev->timer);
 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
  dev->timer.data = (long) dev;
  dev->timer.function = input_repeat_key;
  dev->rep[REP_DELAY] = 250;
  dev->rep[REP_PERIOD] = 33;
 }

 if (!dev->getkeycode && !dev->getkeycode_new)
  dev->getkeycode_new = input_default_getkeycode;

 if (!dev->setkeycode && !dev->setkeycode_new)
  dev->setkeycode_new = input_default_setkeycode;

 dev_set_name(&dev->dev, "input%ld",       /*设备名字input%ld*/
       (unsigned long) atomic_inc_return(&input_no) - 1);

 error = device_add(&dev->dev);     /*添加设备--->设备驱动模型中讲过*/
 
 error = mutex_lock_interruptible(&input_mutex); /*保证互资源斥访问共享*/

 list_add_tail(&dev->node, &input_dev_list);  /*将设备添加到全局的input_dev_list设备链表中*/

 /*handler_list是handler链表(处在事件层,是内核已经实现好的,不需要驱动程序员实现--evdev,misc等) 
 */
 list_for_each_entry(handler, &input_handler_list, node)
  input_attach_handler(dev, handler);         /*下面分析*/  

 mutex_unlock(&input_mutex);

 return 0;
}

/*************************接下来分析input_attach_handler()***************************/

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
 const struct input_device_id *id;
 int error;

 id = input_match_device(handler, dev);    //判断input_dev设备和handler是否相匹配
 if (!id)
  return -ENODEV;

 error = handler->connect(handler, dev, id);    //取得handler的connect函数(以evdev为例--按键/触屏等handler)
 if (error && error != -ENODEV)
  pr_err("failed to attach handler %s to device %s, error: %d\n",
         handler->name, kobject_name(&dev->dev.kobj), error);

 return error;
}

2.4 接下来分析handler->connect()

/*在分析之前首先先对handler有个认识,handler是内核已经帮我们实现好的,
 如mousedev,evdev,joydev,键盘等驱动,不需要我们去写*/
/*设备驱动程序员关心的是input_dev层面的....*/

猜你喜欢

转载自blog.csdn.net/jun_8018/article/details/77586425