static void input_handle_event(struct input_dev *dev,
                               unsigned int type, unsigned int code, int value)
 {
-       int disposition = input_get_disposition(dev, type, code, &value);
+       int disposition;
 
+       /* filter-out events from inhibited devices */
+       if (dev->inhibited)
+               return;
+
+       disposition = input_get_disposition(dev, type, code, &value);
        if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
                add_input_randomness(type, code, value);
 
 
        handle->open++;
 
-       if (dev->users++) {
+       if (dev->users++ || dev->inhibited) {
                /*
-                * Device is already opened, so we can exit immediately and
-                * report success.
+                * Device is already opened and/or inhibited,
+                * so we can exit immediately and report success.
                 */
                goto out;
        }
 
        __input_release_device(handle);
 
-       if (!--dev->users) {
+       if (!dev->inhibited && !--dev->users) {
                if (dev->poller)
                        input_dev_poller_stop(dev->poller);
-
                if (dev->close)
                        dev->close(dev);
        }
 }
 static DEVICE_ATTR(properties, S_IRUGO, input_dev_show_properties, NULL);
 
+static int input_inhibit_device(struct input_dev *dev);
+static int input_uninhibit_device(struct input_dev *dev);
+
+static ssize_t inhibited_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct input_dev *input_dev = to_input_dev(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", input_dev->inhibited);
+}
+
+static ssize_t inhibited_store(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t len)
+{
+       struct input_dev *input_dev = to_input_dev(dev);
+       ssize_t rv;
+       bool inhibited;
+
+       if (strtobool(buf, &inhibited))
+               return -EINVAL;
+
+       if (inhibited)
+               rv = input_inhibit_device(input_dev);
+       else
+               rv = input_uninhibit_device(input_dev);
+
+       if (rv != 0)
+               return rv;
+
+       return len;
+}
+
+static DEVICE_ATTR_RW(inhibited);
+
 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,
+       &dev_attr_inhibited.attr,
        NULL
 };
 
 }
 EXPORT_SYMBOL(input_reset_device);
 
+static int input_inhibit_device(struct input_dev *dev)
+{
+       int ret = 0;
+
+       mutex_lock(&dev->mutex);
+
+       if (dev->inhibited)
+               goto out;
+
+       if (dev->users) {
+               if (dev->close)
+                       dev->close(dev);
+               if (dev->poller)
+                       input_dev_poller_stop(dev->poller);
+       }
+
+       spin_lock_irq(&dev->event_lock);
+       input_dev_release_keys(dev);
+       input_dev_toggle(dev, false);
+       spin_unlock_irq(&dev->event_lock);
+
+       dev->inhibited = true;
+
+out:
+       mutex_unlock(&dev->mutex);
+       return ret;
+}
+
+static int input_uninhibit_device(struct input_dev *dev)
+{
+       int ret = 0;
+
+       mutex_lock(&dev->mutex);
+
+       if (!dev->inhibited)
+               goto out;
+
+       if (dev->users) {
+               if (dev->open) {
+                       ret = dev->open(dev);
+                       if (ret)
+                               goto out;
+               }
+               if (dev->poller)
+                       input_dev_poller_start(dev->poller);
+       }
+
+       dev->inhibited = false;
+       spin_lock_irq(&dev->event_lock);
+       input_dev_toggle(dev, true);
+       spin_unlock_irq(&dev->event_lock);
+
+out:
+       mutex_unlock(&dev->mutex);
+       return ret;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int input_dev_suspend(struct device *dev)
 {
 {
        lockdep_assert_held(&dev->mutex);
 
-       return dev->users > 0;
+       return !dev->inhibited && dev->users > 0;
 }
 EXPORT_SYMBOL_GPL(input_device_enabled);
 
 
  * @open: this method is called when the very first user calls
  *     input_open_device(). The driver must prepare the device
  *     to start generating events (start polling thread,
- *     request an IRQ, submit URB, etc.)
+ *     request an IRQ, submit URB, etc.). The meaning of open() is
+ *     to start providing events to the input core.
  * @close: this method is called when the very last user calls
- *     input_close_device().
+ *     input_close_device(). The meaning of close() is to stop
+ *     providing events to the input core.
  * @flush: purges the device. Most commonly used to get rid of force
  *     feedback effects loaded into the device when disconnecting
  *     from it
  *     and needs not be explicitly unregistered or freed.
  * @timestamp: storage for a timestamp set by input_set_timestamp called
  *  by a driver
+ * @inhibited: indicates that the input device is inhibited. If that is
+ * the case then input core ignores any events generated by the device.
+ * Device's close() is called when it is being inhibited and its open()
+ * is called when it is being uninhibited.
  */
 struct input_dev {
        const char *name;
        bool devres_managed;
 
        ktime_t timestamp[INPUT_CLK_MAX];
+
+       bool inhibited;
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)