⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Input uevent interface - loading event handlers based on * device bitfields. */static int input_add_uevent_bm_var(struct kobj_uevent_env *env,				   const char *name, unsigned long *bitmap, int max){	int len;	if (add_uevent_var(env, "%s=", name))		return -ENOMEM;	len = input_print_bitmap(&env->buf[env->buflen - 1],				 sizeof(env->buf) - env->buflen,				 bitmap, max, 0);	if (len >= (sizeof(env->buf) - env->buflen))		return -ENOMEM;	env->buflen += len;	return 0;}static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,					 struct input_dev *dev){	int len;	if (add_uevent_var(env, "MODALIAS="))		return -ENOMEM;	len = input_print_modalias(&env->buf[env->buflen - 1],				   sizeof(env->buf) - env->buflen,				   dev, 0);	if (len >= (sizeof(env->buf) - env->buflen))		return -ENOMEM;	env->buflen += len;	return 0;}#define INPUT_ADD_HOTPLUG_VAR(fmt, val...)				\	do {								\		int err = add_uevent_var(env, fmt, val);		\		if (err)						\			return err;					\	} while (0)#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max)				\	do {								\		int err = input_add_uevent_bm_var(env, name, bm, max);	\		if (err)						\			return err;					\	} while (0)#define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev)				\	do {								\		int err = input_add_uevent_modalias_var(env, dev);	\		if (err)						\			return err;					\	} while (0)static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env){	struct input_dev *dev = to_input_dev(device);	INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x",				dev->id.bustype, dev->id.vendor,				dev->id.product, dev->id.version);	if (dev->name)		INPUT_ADD_HOTPLUG_VAR("NAME=\"%s\"", dev->name);	if (dev->phys)		INPUT_ADD_HOTPLUG_VAR("PHYS=\"%s\"", dev->phys);	if (dev->uniq)		INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);	INPUT_ADD_HOTPLUG_BM_VAR("EV=", dev->evbit, EV_MAX);	if (test_bit(EV_KEY, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("KEY=", dev->keybit, KEY_MAX);	if (test_bit(EV_REL, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);	if (test_bit(EV_ABS, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);	if (test_bit(EV_MSC, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);	if (test_bit(EV_LED, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("LED=", dev->ledbit, LED_MAX);	if (test_bit(EV_SND, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("SND=", dev->sndbit, SND_MAX);	if (test_bit(EV_FF, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);	if (test_bit(EV_SW, dev->evbit))		INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);	INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);	return 0;}static struct device_type input_dev_type = {	.groups		= input_dev_attr_groups,	.release	= input_dev_release,	.uevent		= input_dev_uevent,};struct class input_class = {	.name		= "input",};EXPORT_SYMBOL_GPL(input_class);/** * input_allocate_device - allocate memory for new input device * * Returns prepared struct input_dev or NULL. * * NOTE: Use input_free_device() to free devices that have not been * registered; input_unregister_device() should be used for already * registered devices. */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;}EXPORT_SYMBOL(input_allocate_device);/** * input_free_device - free memory occupied by input_dev structure * @dev: input device to free * * This function should only be used if input_register_device() * was not called yet or if it failed. Once device was registered * use input_unregister_device() and memory will be freed once last * reference to the device is dropped. * * Device should be allocated by input_allocate_device(). * * NOTE: If there are references to the input device then memory * will not be freed until last reference is dropped. */void input_free_device(struct input_dev *dev){	if (dev)		input_put_device(dev);}EXPORT_SYMBOL(input_free_device);/** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event * @type: type of the event (EV_KEY, EV_REL, etc...) * @code: event code * * In addition to setting up corresponding bit in appropriate capability * bitmap the function also adjusts dev->evbit. */void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code){	switch (type) {	case EV_KEY:		__set_bit(code, dev->keybit);		break;	case EV_REL:		__set_bit(code, dev->relbit);		break;	case EV_ABS:		__set_bit(code, dev->absbit);		break;	case EV_MSC:		__set_bit(code, dev->mscbit);		break;	case EV_SW:		__set_bit(code, dev->swbit);		break;	case EV_LED:		__set_bit(code, dev->ledbit);		break;	case EV_SND:		__set_bit(code, dev->sndbit);		break;	case EV_FF:		__set_bit(code, dev->ffbit);		break;	case EV_PWR:		/* do nothing */		break;	default:		printk(KERN_ERR			"input_set_capability: unknown type %u (code %u)\n",			type, code);		dump_stack();		return;	}	__set_bit(type, dev->evbit);}EXPORT_SYMBOL(input_set_capability);/** * input_register_device - register device with input core * @dev: device to be registered * * This function registers device with input core. The device must be * allocated with input_allocate_device() and all it's capabilities * set up before registering. * If function fails the device must be freed with input_free_device(). * Once device has been successfully registered it can be unregistered * with input_unregister_device(); input_free_device() should not be * called in this case. */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);	/*	 * 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 = input_default_getkeycode;	if (!dev->setkeycode)		dev->setkeycode = input_default_setkeycode;	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);	if (dev->cdev.dev)		dev->dev.parent = dev->cdev.dev;	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;}EXPORT_SYMBOL(input_register_device);/** * input_unregister_device - unregister previously registered device * @dev: device to be unregistered * * This function unregisters an input device. Once device is unregistered * the caller should not try to access it as it may get freed at any moment. */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);}EXPORT_SYMBOL(input_unregister_device);/** * input_register_handler - register a new input handler * @handler: handler to be registered * * This function registers a new input handler (interface) for input * devices in the system and attaches it to all input devices that * are compatible with the handler. */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;}EXPORT_SYMBOL(input_register_handler);/** * input_unregister_handler - unregisters an input handler * @handler: handler to be unregistered * * This function disconnects a handler from its input devices and * removes it from lists of known handlers. */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);}EXPORT_SYMBOL(input_unregister_handler);/** * input_register_handle - register a new input handle * @handle: handle to register * * This function puts a new input handle onto device's * and handler's lists so that events can flow through * it once it is opened using input_open_device(). * * This function is supposed to be called from handler's * connect() method. */int input_register_handle(struct input_handle *handle){	struct input_handler *handler = handle->handler;	struct input_dev *dev = handle->dev;	int error;	/*	 * We take dev->mutex here to prevent race with	 * input_release_device().	 */	error = mutex_lock_interruptible(&dev->mutex);	if (error)		return error;	list_add_tail_rcu(&handle->d_node, &dev->h_list);	mutex_unlock(&dev->mutex);	synchronize_rcu();	/*	 * Since we are supposed to be called from ->connect()	 * which is mutually exclusive with ->disconnect()	 * we can't be racing with input_unregister_handle()	 * and so separate lock is not needed here.	 */	list_add_tail(&handle->h_node, &handler->h_list);	if (handler->start)		handler->start(handle);	return 0;}EXPORT_SYMBOL(input_register_handle);/** * input_unregister_handle - unregister an input handle * @handle: handle to unregister * * This function removes input handle from device's * and handler's lists. * * This function is supposed to be called from handler's * disconnect() method. */void input_unregister_handle(struct input_handle *handle){	struct input_dev *dev = handle->dev;	list_del_init(&handle->h_node);	/*	 * Take dev->mutex to prevent race with input_release_device().	 */	mutex_lock(&dev->mutex);	list_del_rcu(&handle->d_node);	mutex_unlock(&dev->mutex);	synchronize_rcu();}EXPORT_SYMBOL(input_unregister_handle);static int input_open_file(struct inode *inode, struct file *file){	struct input_handler *handler = input_table[iminor(inode) >> 5];	const 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 const struct file_operations input_fops = {	.owner = THIS_MODULE,	.open = input_open_file,};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;}static void __exit input_exit(void){	input_proc_exit();	unregister_chrdev(INPUT_MAJOR, "input");	class_unregister(&input_class);}subsys_initcall(input_init);module_exit(input_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -