📄 input.c
字号:
if (dev->name) { envp[i++] = scratch; scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; } if (dev->phys) { envp[i++] = scratch; scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; } SPRINTF_BIT_A(evbit, "EV=", EV_MAX); SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY); SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL); SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS); SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC); SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED); SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND); SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF); envp[i++] = NULL;#ifdef INPUT_DEBUG printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n", argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);#endif value = call_usermodehelper(argv [0], argv, envp, 0); kfree(buf); kfree(envp);#ifdef INPUT_DEBUG if (value != 0) printk(KERN_DEBUG "input.c: hotplug returned %d\n", value);#endif}#endifvoid input_register_device(struct input_dev *dev){ struct input_handle *handle; struct input_handler *handler; struct input_device_id *id; set_bit(EV_SYN, dev->evbit); /* * 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; } INIT_LIST_HEAD(&dev->h_list); list_add_tail(&dev->node, &input_dev_list); list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle);#ifdef CONFIG_HOTPLUG input_call_hotplug("add", dev);#endif#ifdef CONFIG_PROC_FS input_devices_state++; wake_up(&input_devices_poll_wait);#endif}void input_unregister_device(struct input_dev *dev){ struct list_head * node, * next; if (!dev) return; if (dev->pm_dev) pm_unregister(dev->pm_dev); del_timer_sync(&dev->timer); list_for_each_safe(node, next, &dev->h_list) { struct input_handle * handle = to_handle(node); list_del_init(&handle->d_node); list_del_init(&handle->h_node); handle->handler->disconnect(handle); }#ifdef CONFIG_HOTPLUG input_call_hotplug("remove", dev);#endif list_del_init(&dev->node);#ifdef CONFIG_PROC_FS input_devices_state++; wake_up(&input_devices_poll_wait);#endif}void input_register_handler(struct input_handler *handler){ struct input_dev *dev; struct input_handle *handle; struct input_device_id *id; if (!handler) return; INIT_LIST_HEAD(&handler->h_list); if (handler->fops != NULL) input_table[handler->minor >> 5] = handler; list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle);#ifdef CONFIG_PROC_FS input_devices_state++; wake_up(&input_devices_poll_wait);#endif}void input_unregister_handler(struct input_handler *handler){ struct list_head * node, * next; list_for_each_safe(node, next, &handler->h_list) { struct input_handle * handle = to_handle_h(node); list_del_init(&handle->h_node); list_del_init(&handle->d_node); handler->disconnect(handle); } list_del_init(&handler->node); if (handler->fops != NULL) input_table[handler->minor >> 5] = NULL;#ifdef CONFIG_PROC_FS input_devices_state++; wake_up(&input_devices_poll_wait);#endif}static int input_open_file(struct inode *inode, struct file *file){ struct input_handler *handler = input_table[iminor(inode) >> 5]; struct file_operations *old_fops, *new_fops = NULL; int err; /* No load-on-demand here? */ if (!handler || !(new_fops = fops_get(handler->fops))) return -ENODEV; /* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */ if (!new_fops->open) { fops_put(new_fops); return -ENODEV; } 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); return err;}static struct file_operations input_fops = { .owner = THIS_MODULE, .open = input_open_file,};#ifdef CONFIG_PROC_FS#define SPRINTF_BIT_B(bit, name, max) \ do { \ len += sprintf(buf + len, "B: %s", name); \ for (i = NBITS(max) - 1; i >= 0; i--) \ if (dev->bit[i]) break; \ for (; i >= 0; i--) \ len += sprintf(buf + len, "%lx ", dev->bit[i]); \ len += sprintf(buf + len, "\n"); \ } while (0)#define SPRINTF_BIT_B2(bit, name, max, ev) \ do { \ if (test_bit(ev, dev->evbit)) \ SPRINTF_BIT_B(bit, name, max); \ } while (0)static unsigned int input_devices_poll(struct file *file, poll_table *wait){ int state = input_devices_state; poll_wait(file, &input_devices_poll_wait, wait); if (state != input_devices_state) return POLLIN | POLLRDNORM; return 0;}static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data){ struct input_dev *dev; struct input_handle *handle; off_t at = 0; int i, len, cnt = 0; list_for_each_entry(dev, &input_dev_list, node) { len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : ""); len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : ""); len += sprintf(buf + len, "H: Handlers="); list_for_each_entry(handle, &dev->h_list, d_node) len += sprintf(buf + len, "%s ", handle->name); len += sprintf(buf + len, "\n"); SPRINTF_BIT_B(evbit, "EV=", EV_MAX); SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY); SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL); SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS); SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC); SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); len += sprintf(buf + len, "\n"); at += len; if (at >= pos) { if (!*start) { *start = buf + (pos - (at - len)); cnt = at - pos; } else cnt += len; buf += len; if (cnt >= count) break; } } if (&dev->node == &input_dev_list) *eof = 1; return (count > cnt) ? cnt : count;}static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data){ struct input_handler *handler; off_t at = 0; int len = 0, cnt = 0; int i = 0; list_for_each_entry(handler, &input_handler_list, node) { if (handler->fops) len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n", i++, handler->name, handler->minor); else len = sprintf(buf, "N: Number=%d Name=%s\n", i++, handler->name); at += len; if (at >= pos) { if (!*start) { *start = buf + (pos - (at - len)); cnt = at - pos; } else cnt += len; buf += len; if (cnt >= count) break; } } if (&handler->node == &input_handler_list) *eof = 1; return (count > cnt) ? cnt : count;}static int __init input_proc_init(void){ struct proc_dir_entry *entry; proc_bus_input_dir = proc_mkdir("input", proc_bus); if (proc_bus_input_dir == NULL) return -ENOMEM; proc_bus_input_dir->owner = THIS_MODULE; entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL); if (entry == NULL) { remove_proc_entry("input", proc_bus); return -ENOMEM; } entry->owner = THIS_MODULE; entry->proc_fops->poll = input_devices_poll; entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); if (entry == NULL) { remove_proc_entry("devices", proc_bus_input_dir); remove_proc_entry("input", proc_bus); return -ENOMEM; } entry->owner = THIS_MODULE; return 0;}#else /* !CONFIG_PROC_FS */static inline int input_proc_init(void) { return 0; }#endifstruct class_simple *input_class;static int __init input_init(void){ int retval = -ENOMEM; input_class = class_simple_create(THIS_MODULE, "input"); if (IS_ERR(input_class)) return PTR_ERR(input_class); input_proc_init(); retval = register_chrdev(INPUT_MAJOR, "input", &input_fops); if (retval) { printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR); remove_proc_entry("devices", proc_bus_input_dir); remove_proc_entry("handlers", proc_bus_input_dir); remove_proc_entry("input", proc_bus); class_simple_destroy(input_class); return retval; } retval = devfs_mk_dir("input"); if (retval) { remove_proc_entry("devices", proc_bus_input_dir); remove_proc_entry("handlers", proc_bus_input_dir); remove_proc_entry("input", proc_bus); unregister_chrdev(INPUT_MAJOR, "input"); class_simple_destroy(input_class); } return retval;}static void __exit input_exit(void){ remove_proc_entry("devices", proc_bus_input_dir); remove_proc_entry("handlers", proc_bus_input_dir); remove_proc_entry("input", proc_bus); devfs_remove("input"); unregister_chrdev(INPUT_MAJOR, "input"); class_simple_destroy(input_class);}subsys_initcall(input_init);module_exit(input_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -