]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/input/input.c
Input: da9063 - fix capability and drop KEY_SLEEP
[linux.git] / drivers / input / input.c
index 7f3c5fcb9ed6e6b4a618601dd41efa8b0dbdbe60..55086279d044e752e2e009639d36bb89e2462f4d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include "input-compat.h"
+#include "input-poller.h"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -396,6 +397,13 @@ static void input_handle_event(struct input_dev *dev,
                if (dev->num_vals >= 2)
                        input_pass_values(dev, dev->vals, dev->num_vals);
                dev->num_vals = 0;
+               /*
+                * Reset the timestamp on flush so we won't end up
+                * with a stale one. Note we only need to reset the
+                * monolithic one as we use its presence when deciding
+                * whether to generate a synthetic timestamp.
+                */
+               dev->timestamp[INPUT_CLK_MONO] = ktime_set(0, 0);
        } else if (dev->num_vals >= dev->max_vals - 2) {
                dev->vals[dev->num_vals++] = input_value_sync;
                input_pass_values(dev, dev->vals, dev->num_vals);
@@ -603,20 +611,31 @@ int input_open_device(struct input_handle *handle)
 
        handle->open++;
 
-       if (!dev->users++ && dev->open)
-               retval = dev->open(dev);
+       if (dev->users++) {
+               /*
+                * Device is already opened, so we can exit immediately and
+                * report success.
+                */
+               goto out;
+       }
 
-       if (retval) {
-               dev->users--;
-               if (!--handle->open) {
+       if (dev->open) {
+               retval = dev->open(dev);
+               if (retval) {
+                       dev->users--;
+                       handle->open--;
                        /*
                         * Make sure we are not delivering any more events
                         * through this handle
                         */
                        synchronize_rcu();
+                       goto out;
                }
        }
 
+       if (dev->poller)
+               input_dev_poller_start(dev->poller);
+
  out:
        mutex_unlock(&dev->mutex);
        return retval;
@@ -655,8 +674,13 @@ void input_close_device(struct input_handle *handle)
 
        __input_release_device(handle);
 
-       if (!--dev->users && dev->close)
-               dev->close(dev);
+       if (!--dev->users) {
+               if (dev->poller)
+                       input_dev_poller_stop(dev->poller);
+
+               if (dev->close)
+                       dev->close(dev);
+       }
 
        if (!--handle->open) {
                /*
@@ -1502,6 +1526,7 @@ static const struct attribute_group *input_dev_attr_groups[] = {
        &input_dev_attr_group,
        &input_dev_id_attr_group,
        &input_dev_caps_attr_group,
+       &input_poller_attribute_group,
        NULL
 };
 
@@ -1511,6 +1536,7 @@ static void input_dev_release(struct device *device)
 
        input_ff_destroy(dev);
        input_mt_destroy_slots(dev);
+       kfree(dev->poller);
        kfree(dev->absinfo);
        kfree(dev->vals);
        kfree(dev);
@@ -1894,6 +1920,46 @@ void input_free_device(struct input_dev *dev)
 }
 EXPORT_SYMBOL(input_free_device);
 
+/**
+ * input_set_timestamp - set timestamp for input events
+ * @dev: input device to set timestamp for
+ * @timestamp: the time at which the event has occurred
+ *   in CLOCK_MONOTONIC
+ *
+ * This function is intended to provide to the input system a more
+ * accurate time of when an event actually occurred. The driver should
+ * call this function as soon as a timestamp is acquired ensuring
+ * clock conversions in input_set_timestamp are done correctly.
+ *
+ * The system entering suspend state between timestamp acquisition and
+ * calling input_set_timestamp can result in inaccurate conversions.
+ */
+void input_set_timestamp(struct input_dev *dev, ktime_t timestamp)
+{
+       dev->timestamp[INPUT_CLK_MONO] = timestamp;
+       dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp);
+       dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(timestamp,
+                                                          TK_OFFS_BOOT);
+}
+EXPORT_SYMBOL(input_set_timestamp);
+
+/**
+ * input_get_timestamp - get timestamp for input events
+ * @dev: input device to get timestamp from
+ *
+ * A valid timestamp is a timestamp of non-zero value.
+ */
+ktime_t *input_get_timestamp(struct input_dev *dev)
+{
+       const ktime_t invalid_timestamp = ktime_set(0, 0);
+
+       if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp))
+               input_set_timestamp(dev, ktime_get());
+
+       return dev->timestamp;
+}
+EXPORT_SYMBOL(input_get_timestamp);
+
 /**
  * input_set_capability - mark device as capable of a certain event
  * @dev: device that is capable of emitting or accepting event
@@ -2135,6 +2201,9 @@ int input_register_device(struct input_dev *dev)
        if (!dev->setkeycode)
                dev->setkeycode = input_default_setkeycode;
 
+       if (dev->poller)
+               input_dev_poller_finalize(dev->poller);
+
        error = device_add(&dev->dev);
        if (error)
                goto err_free_vals;