aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-22 18:24:26 +0100
committerThomas Gleixner <tglx@linutronix.de>2011-02-22 18:41:48 +0100
commit695884fb8acd9857e0e7120ccb2150e30f4b8fef (patch)
tree49aa424c1a021ce432e9fa5ea29d37a23e4e30cc /drivers/input/input.c
parent5df91509d324d44cfb11e55d9cb02fe18b53b045 (diff)
parent04bea68b2f0eeebb089ecc67b618795925268b4a (diff)
downloadkernel_samsung_tuna-695884fb8acd9857e0e7120ccb2150e30f4b8fef.zip
kernel_samsung_tuna-695884fb8acd9857e0e7120ccb2150e30f4b8fef.tar.gz
kernel_samsung_tuna-695884fb8acd9857e0e7120ccb2150e30f4b8fef.tar.bz2
Merge branch 'devicetree/for-x86' of git://git.secretlab.ca/git/linux-2.6 into x86/platform
Reason: x86 devicetree support for ce4100 depends on those device tree changes scheduled for .39. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r--drivers/input/input.c181
1 files changed, 94 insertions, 87 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index d092ef9..7985114 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -10,9 +10,11 @@
* the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
+
#include <linux/init.h>
#include <linux/types.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
@@ -24,7 +26,6 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
-#include <linux/smp_lock.h>
#include "input-compat.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
@@ -74,6 +75,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
* dev->event_lock held and interrupts disabled.
*/
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;
@@ -92,6 +94,15 @@ static void input_pass_event(struct input_dev *dev,
continue;
handler = handle->handler;
+
+ /*
+ * If this is the handler that injected this
+ * particular event we want to skip it to avoid
+ * filters firing again and again.
+ */
+ if (handler == src_handler)
+ continue;
+
if (!handler->filter) {
if (filtered)
break;
@@ -121,7 +132,7 @@ static void input_repeat_key(unsigned long data)
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
- input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
+ input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);
if (dev->sync) {
/*
@@ -130,7 +141,7 @@ static void input_repeat_key(unsigned long data)
* Otherwise assume that the driver will send
* SYN_REPORT once it's done.
*/
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+ input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}
if (dev->rep[REP_PERIOD])
@@ -163,6 +174,7 @@ static void input_stop_autorepeat(struct input_dev *dev)
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
static int input_handle_abs_event(struct input_dev *dev,
+ struct input_handler *src_handler,
unsigned int code, int *pval)
{
bool is_mt_event;
@@ -206,13 +218,15 @@ static int input_handle_abs_event(struct input_dev *dev,
/* Flush pending "slot" event */
if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
- input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
+ input_pass_event(dev, src_handler,
+ EV_ABS, ABS_MT_SLOT, dev->slot);
}
return INPUT_PASS_TO_HANDLERS;
}
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;
@@ -265,7 +279,8 @@ static void input_handle_event(struct input_dev *dev,
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX))
- disposition = input_handle_abs_event(dev, code, &value);
+ disposition = input_handle_abs_event(dev, src_handler,
+ code, &value);
break;
@@ -323,7 +338,7 @@ static void input_handle_event(struct input_dev *dev,
dev->event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS)
- input_pass_event(dev, type, code, value);
+ input_pass_event(dev, src_handler, type, code, value);
}
/**
@@ -352,7 +367,7 @@ void input_event(struct input_dev *dev,
spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value);
- input_handle_event(dev, type, code, value);
+ input_handle_event(dev, NULL, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
@@ -382,7 +397,8 @@ void input_inject_event(struct input_handle *handle,
rcu_read_lock();
grab = rcu_dereference(dev->grab);
if (!grab || grab == handle)
- input_handle_event(dev, type, code, value);
+ input_handle_event(dev, handle->handler,
+ type, code, value);
rcu_read_unlock();
spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -595,10 +611,10 @@ static void input_dev_release_keys(struct input_dev *dev)
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
- input_pass_event(dev, EV_KEY, code, 0);
+ input_pass_event(dev, NULL, EV_KEY, code, 0);
}
}
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+ input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}
}
@@ -738,7 +754,7 @@ static int input_default_setkeycode(struct input_dev *dev,
if (index >= dev->keycodemax)
return -EINVAL;
- if (dev->keycodesize < sizeof(dev->keycode) &&
+ if (dev->keycodesize < sizeof(ke->keycode) &&
(ke->keycode >> (dev->keycodesize * 8)))
return -EINVAL;
@@ -873,9 +889,9 @@ int input_set_keycode(struct input_dev *dev,
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(old_keycode, dev->key)) {
- input_pass_event(dev, EV_KEY, old_keycode, 0);
+ input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
if (dev->sync)
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+ input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}
out:
@@ -944,10 +960,8 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
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);
+ pr_err("failed to attach handler %s to device %s, error: %d\n",
+ handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
@@ -1095,6 +1109,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "%s ", handle->name);
seq_putc(seq, '\n');
+ input_seq_print_bitmap(seq, "PROP", dev->propbit, INPUT_PROP_MAX);
+
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);
@@ -1318,11 +1334,26 @@ static ssize_t input_dev_show_modalias(struct device *dev,
}
static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
+ int max, int add_cr);
+
+static ssize_t input_dev_show_properties(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input_dev = to_input_dev(dev);
+ int len = input_print_bitmap(buf, PAGE_SIZE, input_dev->propbit,
+ INPUT_PROP_MAX, true);
+ return min_t(int, len, PAGE_SIZE);
+}
+static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
+
static struct attribute *input_dev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_phys.attr,
&dev_attr_uniq.attr,
&dev_attr_modalias.attr,
+ &dev_attr_properties.attr,
NULL
};
@@ -1456,7 +1487,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
{
int len;
- if (add_uevent_var(env, "%s=", name))
+ if (add_uevent_var(env, "%s", name))
return -ENOMEM;
len = input_print_bitmap(&env->buf[env->buflen - 1],
@@ -1522,6 +1553,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
if (dev->uniq)
INPUT_ADD_HOTPLUG_VAR("UNIQ=\"%s\"", dev->uniq);
+ INPUT_ADD_HOTPLUG_BM_VAR("PROP=", dev->propbit, INPUT_PROP_MAX);
+
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);
@@ -1565,8 +1598,7 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
} \
} while (0)
-#ifdef CONFIG_PM
-static void input_dev_reset(struct input_dev *dev, bool activate)
+static void input_dev_toggle(struct input_dev *dev, bool activate)
{
if (!dev->event)
return;
@@ -1580,12 +1612,44 @@ static void input_dev_reset(struct input_dev *dev, bool activate)
}
}
+/**
+ * input_reset_device() - reset/restore the state of input device
+ * @dev: input device whose state needs to be reset
+ *
+ * This function tries to reset the state of an opened input device and
+ * bring internal state and state if the hardware in sync with each other.
+ * We mark all keys as released, restore LED state, repeat rate, etc.
+ */
+void input_reset_device(struct input_dev *dev)
+{
+ mutex_lock(&dev->mutex);
+
+ if (dev->users) {
+ input_dev_toggle(dev, true);
+
+ /*
+ * Keys that have been pressed at suspend time are unlikely
+ * to be still pressed when we resume.
+ */
+ spin_lock_irq(&dev->event_lock);
+ input_dev_release_keys(dev);
+ spin_unlock_irq(&dev->event_lock);
+ }
+
+ mutex_unlock(&dev->mutex);
+}
+EXPORT_SYMBOL(input_reset_device);
+
+#ifdef CONFIG_PM
static int input_dev_suspend(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
mutex_lock(&input_dev->mutex);
- input_dev_reset(input_dev, false);
+
+ if (input_dev->users)
+ input_dev_toggle(input_dev, false);
+
mutex_unlock(&input_dev->mutex);
return 0;
@@ -1595,18 +1659,7 @@ static int input_dev_resume(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
- mutex_lock(&input_dev->mutex);
- input_dev_reset(input_dev, true);
-
- /*
- * Keys that have been pressed at suspend time are unlikely
- * to be still pressed when we resume.
- */
- spin_lock_irq(&input_dev->event_lock);
- input_dev_release_keys(input_dev);
- spin_unlock_irq(&input_dev->event_lock);
-
- mutex_unlock(&input_dev->mutex);
+ input_reset_device(input_dev);
return 0;
}
@@ -1691,52 +1744,6 @@ void input_free_device(struct input_dev *dev)
EXPORT_SYMBOL(input_free_device);
/**
- * input_mt_create_slots() - create MT input slots
- * @dev: input device supporting MT events and finger tracking
- * @num_slots: number of slots used by the device
- *
- * This function allocates all necessary memory for MT slot handling in the
- * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
- * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
- */
-int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
-{
- int i;
-
- if (!num_slots)
- return 0;
-
- dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
- if (!dev->mt)
- return -ENOMEM;
-
- dev->mtsize = num_slots;
- input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
-
- /* Mark slots as 'unused' */
- for (i = 0; i < num_slots; i++)
- dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1;
-
- return 0;
-}
-EXPORT_SYMBOL(input_mt_create_slots);
-
-/**
- * input_mt_destroy_slots() - frees the MT slots of the input device
- * @dev: input device with allocated MT slots
- *
- * This function is only needed in error path as the input core will
- * automatically free the MT slots when the device is destroyed.
- */
-void input_mt_destroy_slots(struct input_dev *dev)
-{
- kfree(dev->mt);
- dev->mt = NULL;
- dev->mtsize = 0;
-}
-EXPORT_SYMBOL(input_mt_destroy_slots);
-
-/**
* 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...)
@@ -1785,9 +1792,8 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
break;
default:
- printk(KERN_ERR
- "input_set_capability: unknown type %u (code %u)\n",
- type, code);
+ pr_err("input_set_capability: unknown type %u (code %u)\n",
+ type, code);
dump_stack();
return;
}
@@ -1869,8 +1875,9 @@ int input_register_device(struct input_dev *dev)
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");
+ pr_info("%s as %s\n",
+ dev->name ? dev->name : "Unspecified device",
+ path ? path : "N/A");
kfree(path);
error = mutex_lock_interruptible(&input_mutex);
@@ -2152,7 +2159,7 @@ static int __init input_init(void)
err = class_register(&input_class);
if (err) {
- printk(KERN_ERR "input: unable to register input_dev class\n");
+ pr_err("unable to register input_dev class\n");
return err;
}
@@ -2162,7 +2169,7 @@ static int __init input_init(void)
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
if (err) {
- printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
+ pr_err("unable to register char major %d", INPUT_MAJOR);
goto fail2;
}