一. 输入设备结构体
1. input_dev 输入设备
- struct input_dev {
- const char *name;
- const char *phys;
- const char *uniq;
- struct input_id id;
-
- unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
- unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
- unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
- 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 hint_events_per_packet;
- 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);
-
- struct ff_device *ff;
- unsigned int repeat_key;
- struct timer_list timer;
- int rep[REP_CNT];
- struct input_mt_slot *mt;
- int mtsize;
- int slot;
- struct input_absinfo *absinfo;
- 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;
- unsigned int users;
- bool going_away;
- bool sync;
- struct device dev;
- struct list_head h_list;
- struct list_head node;
- };
2. input_handler 输入处理器
- struct input_handler {
- void *private;
- void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
- bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
- bool (*match)(struct input_handler *handler, struct input_dev *dev);
- int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
- void (*disconnect)(struct input_handle *handle);
- void (*start)(struct input_handle *handle);
- const struct file_operations *fops;
- int minor;
- const char *name;
- const struct input_device_id *id_table;
- struct list_head h_list;
- struct list_head node;
- };
二. 输入系统初始化
1 input_init
- static int __init input_init(void)
- {
- int err;
-
- err = class_register(&input_class);
- if (err) {
- printk(KERN_ERR "input: unable to register input_dev class\n");
- return err;
- }
-
- err = input_proc_init();
- if (err)
- goto fail1;
-
- err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
- if (err) {
- printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
- goto fail2;
- }
-
- return 0;
-
- fail2: input_proc_exit();
- fail1: class_unregister(&input_class);
- return err;
- }
2. /proc 接口
2.1 创建/proc/bus/input下的文件
- static int __init input_proc_init(void)
- {
- struct proc_dir_entry *entry;
-
- proc_bus_input_dir = proc_mkdir("bus/input", NULL);
- if (!proc_bus_input_dir)
- return -ENOMEM;
-
- entry = proc_create("devices", 0, proc_bus_input_dir,&input_devices_fileops);
- if (!entry)
- goto fail1;
-
- entry = proc_create("handlers", 0, proc_bus_input_dir,&input_handlers_fileops);
- if (!entry)
- goto fail2;
-
- return 0;
-
- fail2: remove_proc_entry("devices", proc_bus_input_dir);
- fail1: remove_proc_entry("bus/input", NULL);
- return -ENOMEM;
- }
2.2 devices文件
- static const struct file_operations input_devices_fileops = {
- .owner = THIS_MODULE,
- .open = input_proc_devices_open,
- .poll = input_proc_devices_poll,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
- };
2.2.1 限于篇幅及省略啰嗦
这里当我们去cat /proc/bus/input/devices时候,会调用input_proc_devices_open函数,接着调用seq_open(file, &input_devices_seq_ops),捆绑了input_devices_seq_ops操作函数集,
其seq_operations函数集中声明了.show方法为input_devices_seq_show,该方法打印了些信息到seq文件,接着cat命令会调用read方法,read方法会调用.show方法,
接着把打印到文件的信息复制用户空间的缓冲区中.这里主要看看.show方法吧
2.2.2 input_devices_seq_show
- static int input_devices_seq_show(struct seq_file *seq, void *v)
- {
- struct input_dev *dev = container_of(v, struct input_dev, node);
- const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
- struct input_handle *handle;
-
- seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version);
-
- seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
- seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
- seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
- seq_printf(seq, "U: Uniq=%s\n", dev->uniq ? dev->uniq : "");
- seq_printf(seq, "H: Handlers=");
-
- list_for_each_entry(handle, &dev->h_list, d_node)
- seq_printf(seq, "%s ", handle->name);
- seq_putc(seq, '\n');
-
- input_seq_print_bitmap(seq, "EV", dev->evbit, EV_MAX);
- if (test_bit(EV_KEY, dev->evbit))
- input_seq_print_bitmap(seq, "KEY", dev->keybit, KEY_MAX);
- if (test_bit(EV_REL, dev->evbit))
- input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
- if (test_bit(EV_ABS, dev->evbit))
- input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
- if (test_bit(EV_MSC, dev->evbit))
- input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
- if (test_bit(EV_LED, dev->evbit))
- input_seq_print_bitmap(seq, "LED", dev->ledbit, LED_MAX);
- if (test_bit(EV_SND, dev->evbit))
- input_seq_print_bitmap(seq, "SND", dev->sndbit, SND_MAX);
- if (test_bit(EV_FF, dev->evbit))
- input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
- if (test_bit(EV_SW, dev->evbit))
- input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
-
- seq_putc(seq, '\n');
-
- kfree(path);
- return 0;
- }
打印效果大致如下:因设备不同而异
- cat devices
- I: Bus=0019 Vendor=0000 Product=0001 Version=0000
- N: Name="Power Button"
- P: Phys=LNXPWRBN/button/input0
- S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
- U: Uniq=
- H: Handlers=kbd event0
- B: EV=3
- B: KEY=100000 0 0 0
-
- I: Bus=0017 Vendor=0001 Product=0001 Version=0100
- N: Name="Macintosh mouse button emulation"
- P: Phys=
- S: Sysfs=/devices/virtual/input/input1
- U: Uniq=
- H: Handlers=mouse0 event1
- B: EV=7
- B: KEY=70000 0 0 0 0 0 0 0 0
- B: REL=3
这里可以根据Bus值得知该输入设备是基于什么总线的
- #define BUS_PCI 0x01
- #define BUS_ISAPNP 0x02
- #define BUS_USB 0x03
- #define BUS_HIL 0x04
- #define BUS_BLUETOOTH 0x05
- #define BUS_VIRTUAL 0x06
- #define BUS_ISA 0x10
- #define BUS_I8042 0x11
- #define BUS_XTKBD 0x12
- #define BUS_RS232 0x13
- #define BUS_GAMEPORT 0x14
- #define BUS_PARPORT 0x15
- #define BUS_AMIGA 0x16
- #define BUS_ADB 0x17
- #define BUS_I2C 0x18
- #define BUS_HOST 0x19
- #define BUS_GSC 0x1A
- #define BUS_ATARI 0x1B
- #define BUS_SPI 0x1C
2.3 handlers文件
- static const struct file_operations input_handlers_fileops = {
- .owner = THIS_MODULE,
- .open = input_proc_handlers_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
- };
2.3.1
这里当我们去cat /proc/bus/input/handlers时候,会调用input_proc_handlers_open函数,接着调用seq_open(file, &input_handlers_seq_ops),捆绑了input_handlers_seq_ops操作函数集,
其seq_operations函数集中声明了.show方法为input_handlers_seq_show,该方法打印了些信息到seq文件,接着cat命令会调用read方法,read方法会调用.show方法,
接着把打印到文件的信息复制用户空间的缓冲区中.这里主要看看.show方法吧
- static int input_handlers_seq_show(struct seq_file *seq, void *v)
- {
- struct input_handler *handler = container_of(v, struct input_handler, node);
- union input_seq_state *state = (union input_seq_state *)&seq->private;
-
- seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
- if (handler->filter)
- seq_puts(seq, " (filter)");
- if (handler->fops)
- seq_printf(seq, " Minor=%d", handler->minor);
- seq_putc(seq, '\n');
-
- return 0;
- }
我的打印是
- cat handlers
- N: Number=0 Name=rfkill
- N: Number=1 Name=kbd
- N: Number=2 Name=mousedev Minor=32
- N: Number=3 Name=evdev Minor=64
3. 字符设备接口
3.1 主设备号
3.2 input_fops
- static const struct file_operations input_fops = {
- .owner = THIS_MODULE,
- .open = input_open_file,
- .llseek = noop_llseek,
- };
3.2.1 input_open_file
- static int input_open_file(struct inode *inode, struct file *file)
- {
- struct input_handler *handler;
- const struct file_operations *old_fops, *new_fops = NULL;
- int err;
-
- err = mutex_lock_interruptible(&input_mutex);
- if (err)
- return err;
-
-
- handler = input_table[iminor(inode) >> 5];
- if (handler)
- new_fops = fops_get(handler->fops);
-
- mutex_unlock(&input_mutex);
-
-
-
-
-
- if (!new_fops || !new_fops->open) {
- fops_put(new_fops);
- err = -ENODEV;
- goto out;
- }
-
- old_fops = file->f_op;
- file->f_op = new_fops;
-
- err = new_fops->open(inode, file);
- if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
- out:
- return err;
- }
三. 分配input_dev
- 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;
- dev->dev.class = &input_class;
- device_initialize(&dev->dev);
- mutex_init(&dev->mutex);
- spin_lock_init(&dev->event_lock);
- INIT_LIST_HEAD(&dev->h_list);
- INIT_LIST_HEAD(&dev->node);
- __module_get(THIS_MODULE);
- }
-
- return dev;
- }
四. 设置输入设备类型
1.设置标志位的辅助宏
- #define setbit(a, i) (((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) //设置标志位(eg:setbit(EV_KEY,my_input_dev.evbit))
- #define clrbit(a, i) (((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) //清除标志位(eg:setbit(REL_Z,my_input_dev.relbit))
- #define isset(a, i) (((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) //检测某标志位是否设置
- #define isclr(a, i) ((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) //检测某标志位是否清除
2.设置事件类型标志位ev_bit
- #define EV_SYN 0x00 //同步事件
- #define EV_KEY 0x01 //键盘事件
- #define EV_REL 0x02 //相对位移事件
- #define EV_ABS 0x03 //绝对位移事件
- #define EV_MSC 0x04 //杂项事件
- #define EV_SW 0x05 //开关事件
- #define EV_LED 0x11 //led指示灯事件
- #define EV_SND 0x12 //声音事件
- #define EV_REP 0x14 //重复事件
- #define EV_FF 0x15 //强制反馈事件
- #define EV_PWR 0x16
- #define EV_FF_STATUS 0x17
- #define EV_MAX 0x1f
- #define EV_CNT (EV_MAX+1
3.设置对应事件的标志位
标志位的值在include/linux/Input.h中有详细定义
五. 注册注销输入设备
1.1 注册输入设备
- int input_register_device(struct input_dev *dev)
- {
- static atomic_t input_no = ATOMIC_INIT(0);
- struct input_handler *handler;
- const char *path;
- int error;
-
- __set_bit(EV_SYN, dev->evbit);
- __clear_bit(KEY_RESERVED, dev->keybit);
- input_cleanse_bitmasks(dev);
- 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",(unsigned long) atomic_inc_return(&input_no) - 1);
- error = device_add(&dev->dev);
- if (error)
- return error;
- path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
- printk(KERN_INFO "input: %s as %s\n",dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
- kfree(path);
- error = mutex_lock_interruptible(&input_mutex);
- if (error) {
- device_del(&dev->dev);
- return error;
- }
- list_add_tail(&dev->node, &input_dev_list);
- list_for_each_entry(handler, &input_handler_list, node)
- input_attach_handler(dev, handler);
- input_wakeup_procfs_readers();
- mutex_unlock(&input_mutex);
- return 0;
- }
1.2 注销输入设备
- void input_unregister_device(struct input_dev *dev)
- {
- struct input_handle *handle, *next;
- input_disconnect_device(dev);
- mutex_lock(&input_mutex);
- list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
- handle->handler->disconnect(handle);
- WARN_ON(!list_empty(&dev->h_list));
- del_timer_sync(&dev->timer);
- list_del_init(&dev->node);
- input_wakeup_procfs_readers();
- mutex_unlock(&input_mutex);
- device_unregister(&dev->dev);
- }
六. 输入处理器
1.输入处理器的驱动,内核已经帮我们设计好了 eg:evdev.c,tsdev.c,joydev.c,keyboard.c,mousedev.c
2. 以mousedev.c为蓝本分析下处理器驱动的设计
2.1 mousedev_handler的定义
- static struct input_handler mousedev_handler = {
- .event = mousedev_event,
- .connect = mousedev_connect,
- .disconnect = mousedev_disconnect,
- .fops = &mousedev_fops,
- .minor = MOUSEDEV_MINOR_BASE,
- .name = "mousedev",
- .id_table = mousedev_ids,
- };
2.1.1 mousedev_ids
input_device_id的结构体在处理器与设备匹配的时候会用上,mousedev_ids罗列了鼠标的大致分类,flags标记了需要匹配的事件类型
- static const struct input_device_id mousedev_ids[] = {
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
- .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
- .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
- .relbit = { BIT_MASK(REL_X) | BIT_MASK(REL_Y) },
- },
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
- .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
- .relbit = { BIT_MASK(REL_WHEEL) },
- },
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
- .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
- .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
- },
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT |INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
- .keybit = { [BIT_WORD(BTN_TOOL_FINGER)] =BIT_MASK(BTN_TOOL_FINGER) },
- .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |BIT_MASK(ABS_PRESSURE) |BIT_MASK(ABS_TOOL_WIDTH) },
- },
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT |INPUT_DEVICE_ID_MATCH_ABSBIT,
- .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) },
- .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) },
- .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
- },
-
- { },
- };
2.2 处理器的注册
- int input_register_handler(struct input_handler *handler)
- {
- struct input_dev *dev;
- int retval;
- retval = mutex_lock_interruptible(&input_mutex);
- if (retval)
- return retval;
- INIT_LIST_HEAD(&handler->h_list);
- if (handler->fops != NULL) {
- if (input_table[handler->minor >> 5]) {
- retval = -EBUSY;
- goto out;
- }
- input_table[handler->minor >> 5] = handler;
- }
- list_add_tail(&handler->node, &input_handler_list);
- list_for_each_entry(dev, &input_dev_list, node)
- input_attach_handler(dev, handler);
- input_wakeup_procfs_readers();
- out:
- mutex_unlock(&input_mutex);
- return retval;
- }
2.3 处理器的注销
- void input_unregister_handler(struct input_handler *handler)
- {
- struct input_handle *handle, *next;
- mutex_lock(&input_mutex);
- list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
- handler->disconnect(handle);
- WARN_ON(!list_empty(&handler->h_list));
- list_del_init(&handler->node);
- if (handler->fops != NULL)
- input_table[handler->minor >> 5] = NULL;
- input_wakeup_procfs_readers();
- mutex_unlock(&input_mutex);
- }
七. 设备的匹配
1.在输入设备或者输入处理器注册的时候都会遍历全局链表input_handler_list或input_dev_list并调用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);
- if (!id)
- return -ENODEV;
-
- error = handler->connect(handler, dev, id);
- if (error && error != -ENODEV)
- printk(KERN_ERR"input: failed to attach handler %s to device %s,error: %d\n",handler->name, kobject_name(&dev->dev.kobj), error);
-
- return error;
- }
2.input_match_device
- static const struct input_device_id *input_match_device(struct input_handler *handler,struct input_dev *dev)
- {
- const struct input_device_id *id;
- int i;
-
- for (id = handler->id_table; id->flags || id->driver_info; id++) {
-
- if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
- if (id->bustype != dev->id.bustype)
- continue;
-
- if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
- if (id->vendor != dev->id.vendor)
- continue;
-
- if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
- if (id->product != dev->id.product)
- continue;
-
- if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
- if (id->version != dev->id.version)
- continue;
-
- MATCH_BIT(evbit, EV_MAX);
- MATCH_BIT(keybit, KEY_MAX);
- MATCH_BIT(relbit, REL_MAX);
- MATCH_BIT(absbit, ABS_MAX);
- MATCH_BIT(mscbit, MSC_MAX);
- MATCH_BIT(ledbit, LED_MAX);
- MATCH_BIT(sndbit, SND_MAX);
- MATCH_BIT(ffbit, FF_MAX);
- MATCH_BIT(swbit, SW_MAX);
-
- if (!handler->match || handler->match(handler, dev))
- return id;
- }
-
- return NULL;
- }
八. 事件的处理
1.设备需要上报事件(一般在中断处理函数中上报)
- static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_KEY, code, !!value);
- }
-
- static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_REL, code, value);
- }
-
- static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_ABS, code, value);
- }
-
- static inline void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_FF_STATUS, code, value);
- }
-
- static inline void input_report_switch(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_SW, code, !!value);
- }
-
- static inline void input_sync(struct input_dev *dev)
- {
- input_event(dev, EV_SYN, SYN_REPORT, 0);
- }
2.所有上报事件都会调用到input_event函数
- void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
- {
- unsigned long flags;
- if (is_event_supported(type, dev->evbit, EV_MAX)) {
- spin_lock_irqsave(&dev->event_lock, flags);
- add_input_randomness(type, code, value);
- input_handle_event(dev, NULL, type, code, value);
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
- }
3.input_handle_event函数
- static void input_handle_event(struct input_dev *dev,struct input_handler *src_handler,unsigned int type, unsigned int code, int value)
- {
- int disposition = INPUT_IGNORE_EVENT;
- switch (type) {
- case EV_SYN:
- switch (code) {
- case SYN_CONFIG:
- disposition = INPUT_PASS_TO_ALL;
- break;
-
- case SYN_REPORT:
- if (!dev->sync) {
- dev->sync = true;
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
- case SYN_MT_REPORT:
- dev->sync = false;
- disposition = INPUT_PASS_TO_HANDLERS;
- break;
- }
- break;
-
- case EV_KEY:
- if (is_event_supported(code, dev->keybit, KEY_MAX) && !!test_bit(code, dev->key) != value) {
-
- if (value != 2) {
- __change_bit(code, dev->key);
- if (value)
- input_start_autorepeat(dev, code);
- else
- input_stop_autorepeat(dev);
- }
-
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
-
- case EV_SW:
- if (is_event_supported(code, dev->swbit, SW_MAX) &&!!test_bit(code, dev->sw) != value) {
- __change_bit(code, dev->sw);
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
-
- case EV_ABS:
- if (is_event_supported(code, dev->absbit, ABS_MAX))
- disposition = input_handle_abs_event(dev, src_handler,code, &value);
-
- break;
-
- case EV_REL:
- if (is_event_supported(code, dev->relbit, REL_MAX) && value)
- disposition = INPUT_PASS_TO_HANDLERS;
-
- break;
-
- case EV_MSC:
- if (is_event_supported(code, dev->mscbit, MSC_MAX))
- disposition = INPUT_PASS_TO_ALL;
-
- break;
-
- case EV_LED:
- if (is_event_supported(code, dev->ledbit, LED_MAX) &&
- !!test_bit(code, dev->led) != value) {
-
- __change_bit(code, dev->led);
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_SND:
- if (is_event_supported(code, dev->sndbit, SND_MAX)) {
-
- if (!!test_bit(code, dev->snd) != !!value)
- __change_bit(code, dev->snd);
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_REP:
- if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
- dev->rep[code] = value;
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_FF:
- if (value >= 0)
- disposition = INPUT_PASS_TO_ALL;
- break;
-
- case EV_PWR:
- disposition = INPUT_PASS_TO_ALL;
- break;
- }
-
- if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
- dev->sync = false;
-
- if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
- dev->event(dev, type, code, value);
-
- if (disposition & INPUT_PASS_TO_HANDLERS)
- input_pass_event(dev, src_handler, type, code, value);
- }
4.input_pass_event
- static void input_pass_event(struct input_dev *dev,struct input_handler *src_handler,unsigned int type, unsigned int code, int value)
- {
- struct input_handler *handler;
- struct input_handle *handle;
- rcu_read_lock();
- handle = rcu_dereference(dev->grab);
- if (handle)
- handle->handler->event(handle, type, code, value);
- else {
- bool filtered = false;
-
- list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
- if (!handle->open)
- continue;
-
- handler = handle->handler;
-
- if (handler == src_handler)
- continue;
-
- if (!handler->filter) {
- if (filtered)
- break;
- handler->event(handle, type, code, value);
-
- } else if (handler->filter(handle, type, code, value))
- filtered = true;
- }
- }
-
- rcu_read_unlock();
- }