input子系统学习之四:核心层
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了input子系统学习之四:核心层相关的知识,希望对你有一定的参考价值。
核心层:给事件层和设备层提供接口,规范编程接口。
一. 输入子系统核心分析。
1.输入子系统核心对应与/drivers/input/input.c文件,这个也是作为一个模块注册到内核的。所以首先分析模块初始化函数。
1 .cnblogs
2. 输入子系统的核心其他部分都是提供的接口,向上连接事件处理层,向下连接驱动层。
向下对驱动层的接口主要有:
input_allocate_device 这个函数主要是分配一个input_dev接口,并初始化一些基本的成员,这就是我们不能简单用kmalloc分配input_dev结构的原因,因为缺少了一些初始化。
1 /** 2 * input_allocate_device - allocate memory for new input device 3 * 4 * Returns prepared struct input_dev or NULL. 5 * 6 * NOTE: Use input_free_device() to free devices that have not been 7 * registered; input_unregister_device() should be used for already 8 * registered devices. 9 */ 10 struct input_dev *input_allocate_device(void) 11 { 12 struct input_dev *dev; 13 14 dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); 15 if (dev) { 16 dev->dev.type = &input_dev_type; 17 dev->dev.class = &input_class; 18 device_initialize(&dev->dev); 19 mutex_init(&dev->mutex); 20 spin_lock_init(&dev->event_lock); 21 INIT_LIST_HEAD(&dev->h_list); 22 INIT_LIST_HEAD(&dev->node); 23 24 __module_get(THIS_MODULE); 25 } 26 27 return dev; 28 }
input_register_device 注册一个input设备
1 /** 2 * input_register_device - register device with input core 3 * @dev: device to be registered 4 * 5 * This function registers device with input core. The device must be 6 * allocated with input_allocate_device() and all it‘s capabilities 7 * set up before registering. 8 * If function fails the device must be freed with input_free_device(). 9 * Once device has been successfully registered it can be unregistered 10 * with input_unregister_device(); input_free_device() should not be 11 * called in this case. 12 */ 13 int input_register_device(struct input_dev *dev) 14 { 15 static atomic_t input_no = ATOMIC_INIT(0); 16 struct input_handler *handler; 17 const char *path; 18 int error; 19 20 __set_bit(EV_SYN, dev->evbit); 21 /*调用__set_bit()函数设置 input_dev 所支持的事件类型。 22 事件类型由 input_dev 的evbit 成员来表示,在这里将其 EV_SYN 置位, 23 表示设备支持同步事件类型。一个设备可以支持一种或者多种事件类型。*/ 24 25 /* 26 * If delay and period are pre-set by the driver, then autorepeating 27 * is handled by the driver itself and we don‘t do it in input.c. 28 */ 29 30 init_timer(&dev->timer);/*初始化一个 timer 定时器,这个定时器是为处理重复击键而定义的。*/ 31 if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {//若两个都为空,按如下默认设置,主要为自动处理重复按键定义的 32 dev->timer.data = (long) dev; 33 dev->timer.function = input_repeat_key; 34 dev->rep[REP_DELAY] = 250; 35 dev->rep[REP_PERIOD] = 33; 36 } 37 38 if (!dev->getkeycode)//getkeycode函数为空,使用默认的getkeycode函数 39 dev->getkeycode = input_default_getkeycode; 40 41 if (!dev->setkeycode)//setkeycode函数为空,使用默认的setkeycode函数 42 dev->setkeycode = input_default_setkeycode; 43 /* input_default_setkeycode()。input_default_getkeycode()函数用来得到指定位置的键值。 44 input_default_setkeycode()函数用来设置键值。*/ 45 46 dev_set_name(&dev->dev, "input%ld", 47 (unsigned long) atomic_inc_return(&input_no) - 1); 48 /*设置 input_dev 中的 device 的名字,名字以 input0、input1、input2、input3、input4等 49 的形式出现在 sysfs 文件系统中。*/ 50 error = device_add(&dev->dev); 51 if (error) 52 return error; 53 54 path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); 55 printk(KERN_INFO "input: %s as %s\n", 56 dev->name ? dev->name : "Unspecified device", path ? path : "N/A");//打印设备的路径,输出调试信息。 57 kfree(path); 58 59 error = mutex_lock_interruptible(&input_mutex); 60 if (error) { 61 device_del(&dev->dev); 62 return error; 63 } 64 65 list_add_tail(&dev->node, &input_dev_list); 66 /*调用 list_add_tail()函数将 input_dev 加入 input_dev_list 链表中, 67 input_dev_list 链表中包含了系统中所有的 input_dev 设备。*/ 68 list_for_each_entry(handler, &input_handler_list, node) 69 input_attach_handler(dev, handler); 70 /*input_attach_handler()函数用来匹配 input_dev 和 handler,只有匹配成功才能进行下一步的关联操作 */ 71 72 input_wakeup_procfs_readers(); 73 74 mutex_unlock(&input_mutex); 75 76 return 0; 77 }
input_event 这个函数很重要,是驱动层向input子系统核心报告事件的函数,在事件传递过程中再分析。
1 /** 2 * input_event() - report new input event 3 * @dev: device that generated the event 4 * @type: type of the event 5 * @code: event code 6 * @value: value of the event 7 * 8 * This function should be used by drivers implementing various input 9 * devices. See also input_inject_event(). 10 */ 11 12 void input_event(struct input_dev *dev, 13 unsigned int type, unsigned int code, int value) 14 { 15 unsigned long flags; 16 17 if (is_event_supported(type, dev->evbit, EV_MAX)) { 18 19 spin_lock_irqsave(&dev->event_lock, flags); 20 21 /*add_input_randomness()函数对事件发送没有一点用处,只是用来对随机数熵池增加一些贡献, 22 因为按键输入是一种随机事件,所以对熵池是有贡献的。 */ 23 add_input_randomness(type, code, value); 24 input_handle_event(dev, type, code, value); 25 spin_unlock_irqrestore(&dev->event_lock, flags); 26 } 27 }
向上对事件处理层接口主要有:
input_handle_event 判断事件类型,让事件层对应的handler处理
1 static void input_handle_event(struct input_dev *dev, 2 unsigned int type, unsigned int code, int value) 3 { 4 5 int disposition = INPUT_IGNORE_EVENT; 6 /*定义了一个 disposition 变量,该变量表示使用什么样的方式处理事件。 7 此处初始化为 INPUT_IGNORE_EVENT,表示如果后面没有对该变量重新赋值,则忽略这个事件。*/ 8 switch (type) { 9 10 case EV_SYN: 11 switch (code) { 12 case SYN_CONFIG: 13 disposition = INPUT_PASS_TO_ALL; 14 break; 15 16 case SYN_REPORT: 17 if (!dev->sync) { 18 dev->sync = 1; 19 disposition = INPUT_PASS_TO_HANDLERS; 20 } 21 break; 22 case SYN_MT_REPORT: 23 dev->sync = 0; 24 disposition = INPUT_PASS_TO_HANDLERS; 25 break; 26 } 27 break; 28 29 case EV_KEY: 30 if (is_event_supported(code, dev->keybit, KEY_MAX) && 31 !!test_bit(code, dev->key) != value) {//调用 is_event_supported()函数判断是否支持该按键 32 //调用 test_bit()函数来测试按键状态是否改变。 33 if (value != 2) { 34 __change_bit(code, dev->key);/*调用__change_bit()函数改变键的状态。*/ 35 if (value) 36 input_start_autorepeat(dev, code); 37 else 38 input_stop_autorepeat(dev); 39 } 40 41 disposition = INPUT_PASS_TO_HANDLERS; 42 /*将 disposition变量设置为 INPUT_PASS_TO_HANDLERS,表示事件需要 handler 来处理。*/ 43 } 44 break; 45 46 case EV_SW: 47 if (is_event_supported(code, dev->swbit, SW_MAX) && 48 !!test_bit(code, dev->sw) != value) { 49 50 __change_bit(code, dev->sw); 51 disposition = INPUT_PASS_TO_HANDLERS; 52 } 53 break; 54 55 case EV_ABS: 56 if (is_event_supported(code, dev->absbit, ABS_MAX)) { 57 58 if (test_bit(code, input_abs_bypass)) { 59 disposition = INPUT_PASS_TO_HANDLERS; 60 break; 61 } 62 63 value = input_defuzz_abs_event(value, 64 dev->abs[code], dev->absfuzz[code]); 65 66 if (dev->abs[code] != value) { 67 dev->abs[code] = value; 68 disposition = INPUT_PASS_TO_HANDLERS; 69 } 70 } 71 break; 72 73 case EV_REL: 74 if (is_event_supported(code, dev->relbit, REL_MAX) && value) 75 disposition = INPUT_PASS_TO_HANDLERS; 76 77 break; 78 79 case EV_MSC: 80 if (is_event_supported(code, dev->mscbit, MSC_MAX)) 81 disposition = INPUT_PASS_TO_ALL; 82 83 break; 84 85 case EV_LED: 86 if (is_event_supported(code, dev->ledbit, LED_MAX) && 87 !!test_bit(code, dev->led) != value) { 88 89 __change_bit(code, dev->led); 90 disposition = INPUT_PASS_TO_ALL; 91 } 92 break; 93 94 case EV_SND: 95 if (is_event_supported(code, dev->sndbit, SND_MAX)) { 96 97 if (!!test_bit(code, dev->snd) != !!value) 98 __change_bit(code, dev->snd); 99 disposition = INPUT_PASS_TO_ALL; 100 } 101 break; 102 103 case EV_REP: 104 if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) { 105 dev->rep[code] = value; 106 disposition = INPUT_PASS_TO_ALL; 107 } 108 break; 109 110 case EV_FF: 111 if (value >= 0) 112 disposition = INPUT_PASS_TO_ALL; 113 break; 114 115 case EV_PWR: 116 disposition = INPUT_PASS_TO_ALL; 117 break; 118 } 119 120 if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)/*处理 EV_SYN 事件,这里并不对其进行关心。*/ 121 dev->sync = 0; 122 123 /*首先判断 disposition 等于 INPUT_PASS_TO_DEVICE,然后判断 dev->event 是否对其指定了一个处理函数, 124 如果这些条件都满足,则调用自定义的 dev->event()函数处理事件。有些事件是发送给设备, 125 而不是发送给 handler 处理的。event()函数用来向输入子系统报告一个将要发送给设备的事件, 126 例如让 LED 灯点亮事件、蜂鸣器鸣叫事件等。当事件报告给输入子系统后,就要求设备处理这个事件。*/ 127 if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) 128 dev->event(dev, type, code, value); 129 130 if (disposition & INPUT_PASS_TO_HANDLERS) //如果事件需要 handler 处理,则调用 input_pass_event()函数 131 input_pass_event(dev, type, code, value); 132 }
input_pass_event 找到对应的handler,然后调用事件处理器处理
1 static void input_pass_event(struct input_dev *dev, 2 unsigned int type, unsigned int code, int value) 3 { 4 struct input_handle *handle; 5 6 rcu_read_lock(); 7 /*表示如果没有为 input device 强制指定 handler,为 grab 赋值, 8 即就会遍历 input device->h_list 上的 handle 成员。 9 如果该 handle 被打开,表示该设备已经被一个用户进程使用。 10 就会调用与输入设备对应的 handler 的 event()函数。注意, 11 只有在 handle 被打开的情况下才会接收到事件,这就是说, 12 只有设备被用户程序使用时,才有必要向用户空间导出信息。*/ 13 handle = rcu_dereference(dev->grab); 14 if (handle) 15 handle->handler->event(handle, type, code, value); 16 else 17 list_for_each_entry_rcu(handle, &dev->h_list, d_node) 18 if (handle->open) 19 handle->handler->event(handle, 20 type, code, value); 21 rcu_read_unlock(); 22 }
input_attach_handler 将事件处理器和设备进行连接
1 static int input_attach_handler(struct input_dev *dev, struct input_handler *handler) 2 { 3 const struct input_device_id *id;/*输入设备的指针,该结构体表示设备的标识,标识中存储了设备的信息*/ 4 int error; 5 6 if (handler->blacklist && input_match_device(handler->blacklist, dev)) 7 return -ENODEV; 8 /*首先判断 handler 的 blacklist 是否被赋值,如果被赋值,则匹配 blacklist 中的数据跟 dev->id 9 的数据是否匹配。blacklist 是一个 input_device_id*的类型,其指向 input_device_id的一个表, 10 这个表中存放了驱动程序应该忽略的设备。即使在 id_table 中找到支持的项,也应该忽略这种设备。*/ 11 id = input_match_device(handler->id_table, dev); 12 if (!id) 13 return -ENODEV; 14 15 error = handler->connect(handler, dev, id);//连接设备和处理函数 16 if (error && error != -ENODEV) 17 printk(KERN_ERR 18 "input: failed to attach handler %s to device %s, " 19 "error: %d\n", 20 handler->name, kobject_name(&dev->dev.kobj), error); 21 22 return error; 23 }
input_match_device 事件处理器可以对一种或几种类型的事件进行处理,在连接前,先找到支持这类设备的事件处理器
1 static const struct input_device_id *input_match_device(const struct input_device_id *id, 2 struct input_dev *dev) 3 { 4 int i; 5 6 for (; id->flags || id->driver_info; id++) { 7 8 if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) 9 if (id->bustype != dev->id.bustype) 10 continue; 11 12 if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) 13 if (id->vendor != dev->id.vendor) 14 continue; 15 16 if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) 17 if (id->product != dev->id.product) 18 continue; 19 20 if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) 21 if (id->version != dev->id.version) 22 continue; 23 24 MATCH_BIT(evbit, EV_MAX); 25 MATCH_BIT(keybit, KEY_MAX); 26 MATCH_BIT(relbit, REL_MAX); 27 MATCH_BIT(absbit, ABS_MAX); 28 MATCH_BIT(mscbit, MSC_MAX); 29 MATCH_BIT(ledbit, LED_MAX); 30 MATCH_BIT(sndbit, SND_MAX); 31 MATCH_BIT(ffbit, FF_MAX); 32 MATCH_BIT(swbit, SW_MAX); 33 34 return id; 35 } 36 37 return NULL; 38 }
input_register_handler 注册一个事件处理器
1 /** 2 * input_register_handler - register a new input handler 3 * @handler: handler to be registered 4 * 5 * This function registers a new input handler (interface) for input 6 * devices in the system and attaches it to all input devices that 7 * are compatible with the handler. 8 */ 9 int input_register_handler(struct input_handler *handler) 10 { 11 struct input_dev *dev; 12 int retval; 13 14 retval = mutex_lock_interruptible(&input_mutex); 15 if (retval) 16 return retval; 17 18 INIT_LIST_HEAD(&handler->h_list); 19 20 if (handler->fops != NULL) { 21 if (input_table[handler->minor >> 5]) { 22 retval = -EBUSY; 23 goto out; 24 } 25 input_table[handler->minor >> 5] = handler; 26 } 27 28 list_add_tail(&handler->node, &input_handler_list); 29 30 list_for_each_entry(dev, &input_dev_list, node); 31 input_attach_handler(dev, handler); 32 33 input_wakeup_procfs_readers(); 34 35 out: 36 mutex_unlock(&input_mutex); 37 return retval; 38 }
input_register_handle 注册一个input_handle结构
1 /** 2 * input_register_handle - register a new input handle 3 * @handle: handle to register 4 * 5 * This function puts a new input handle onto device‘s 6 * and handler‘s lists so that events can flow through 7 * it once it is opened using input_open_device(). 8 * 9 * This function is supposed to be called from handler‘s 10 * connect() method. 11 */ 12 int input_register_handle(struct input_handle *handle) 13 { 14 struct input_handler *handler = handle->handler; 15 struct input_dev *dev = handle->dev; 16 int error; 17 18 /* 19 * We take dev->mutex here to prevent race with 20 * input_release_device(). 21 */ 22 error = mutex_lock_interruptible(&dev->mutex); 23 if (error) 24 return error; 25 list_add_tail_rcu(&handle->d_node, &dev->h_list); 26 mutex_unlock(&dev->mutex); 27 28 /* 29 * Since we are supposed to be called from ->connect() 30 * which is mutually exclusive with ->disconnect() 31 * we can‘t be racing with input_unregister_handle() 32 * and so separate lock is not needed here. 33 */ 34 list_add_tail(&handle->h_node, &handler->h_list); 35 36 if (handler->start) 37 handler->start(handle); 38 39 return 0; 40 }
以上是关于input子系统学习之四:核心层的主要内容,如果未能解决你的问题,请参考以下文章