@@ -510,6 +510,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
struct evdev *evdev = client->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
+ struct input_event_state st;
struct ff_effect effect;
int __user *ip = (int __user *)p;
int i, t, u, v;
@@ -566,6 +567,24 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return input_set_keycode(dev, t, v);
+ case EVIOCGSTATE:
+ if (copy_from_user(&st, p, sizeof(st)))
+ return -EFAULT;
+
+ error = input_get_event_state(dev, &st);
+ if (error)
+ return error;
+
+ if (copy_to_user(p, &st, sizeof(st)))
+ return -EFAULT;
+
+ return 0;
+
+ case EVIOCSSTATE:
+ if (copy_from_user(&st, p, sizeof(st)))
+ return -EFAULT;
+ return input_set_event_state(dev, &st);
+
case EVIOCRMFF:
return input_ff_erase(dev, (int)(unsigned long) p, file);
@@ -690,6 +690,121 @@ int input_set_keycode(struct input_dev *dev, int scancode, int keycode)
}
EXPORT_SYMBOL(input_set_keycode);
+/**
+ * input_validate_event_state - validates event state
+ * @dev: input device whose event state is being validated
+ * @st: input event state which is to be validated
+ *
+ * This function checks whether contents of given event state
+ * structure (@st) is valid for @dev (i.e it is supported).
+ * Returns 0 when @st is valid, negative error otherwise.
+ *
+ * Function accesses internals of @dev so make sure that
+ * @dev->event_lock is locked.
+ */
+static int input_validate_event_state(struct input_dev *dev,
+ const struct input_event_state *st)
+{
+ unsigned long *bits;
+ unsigned int max;
+
+ BUG_ON(st == NULL);
+
+ /* for now, we support only EV_KEY and EV_SW */
+ switch (st->type) {
+ case EV_KEY:
+ bits = dev->keybit;
+ max = KEY_MAX;
+ break;
+ case EV_SW:
+ bits = dev->swbit;
+ max = SW_MAX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!is_event_supported(st->code, bits, max))
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * input_get_event_state - gets current state of given input event
+ * @dev: device whose event state is being get
+ * @st: buffer where event state is stored
+ *
+ * This function is used to get state of given event. Event is identified
+ * by {@st->code, @st->type} tuple. On success function returns 0, negative
+ * error in case of failure.
+ */
+int input_get_event_state(struct input_dev *dev,
+ struct input_event_state *st)
+{
+ unsigned long flags;
+ int error;
+
+ if (dev->get_event_state == NULL)
+ return -ENOTTY;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ error = input_validate_event_state(dev, st);
+ if (error)
+ goto out;
+
+ error = dev->get_event_state(dev, st);
+out:
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ return error;
+
+}
+EXPORT_SYMBOL(input_get_event_state);
+
+/**
+ * input_set_event_state - sets state of given input event
+ * @dev: device which event is being set
+ * @st: new event state
+ *
+ * Input event state is controlled by this function. Caller must pass valid
+ * @st to the function (@st->code, @st->type and @st->state should be correct).
+ * For example one can disable input event (if this is supported by underlying
+ * driver by doing following:
+ * new_state->state = EVENT_STATE_DISABLE;
+ * error = input_set_event_state(dev, new_state);
+ * if (error)
+ * ...
+ * Function calls the actual implementation function provided by the driver
+ * with @dev->event_lock locked so it cannot sleep.
+ *
+ * If function fails, returns negative error number or 0 on success.
+ */
+int input_set_event_state(struct input_dev *dev,
+ const struct input_event_state *st)
+{
+ unsigned long flags;
+ int error;
+
+ if (dev->set_event_state == NULL)
+ return -ENOTTY;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ error = input_validate_event_state(dev, st);
+ if (error)
+ goto out;
+
+ error = dev->set_event_state(dev, st);
+out:
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ return error;
+
+}
+EXPORT_SYMBOL(input_set_event_state);
+
#define MATCH_BIT(bit, max) \
for (i = 0; i < BITS_TO_LONGS(max); i++) \
if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
@@ -56,6 +56,37 @@ struct input_absinfo {
__s32 resolution;
};
+/**
+ * struct input_event_state - struct used to set/get input event state
+ * @type: input event type (EV_KEY, EV_SW, ..) [user supplied]
+ * @code: input event code [user supplied]
+ * @state: state of the input event (see EVENT_STATE_* below)
+ * @pad: zero padding
+ *
+ * Generated events can have state if underlying event driver supports it.
+ * This way it is possible for example to ask hardware to disable given
+ * event from generating interrupts. In future there might be some other
+ * states event can have (currently only enable/disable is supported).
+ *
+ * This structure is passed to lower-level input event driver to change
+ * @state of given input event. Event is identified by {@type, @code} tuple.
+ *
+ * See functions:
+ * input_get_event_state()
+ * input_set_event_state()
+ *
+ * for more information.
+ */
+struct input_event_state {
+ __u16 type;
+ __u16 code;
+ __u8 state;
+ __u8 pad[3];
+};
+
+#define EVENT_STATE_DISABLE 0 /* event is disabled */
+#define EVENT_STATE_ENABLE 1 /* event is enabled */
+
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */
@@ -67,6 +98,9 @@ struct input_absinfo {
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
+#define EVIOCGSTATE _IOR('E', 0x10, struct input_event_state) /* get event state */
+#define EVIOCSSTATE _IOW('E', 0x11, struct input_event_state) /* set event state */
+
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global keystate */
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
@@ -1024,6 +1058,8 @@ struct ff_effect {
* sparse keymaps. If not supplied default mechanism will be used
* @getkeycode: optional method to retrieve current keymap. If not supplied
* default mechanism will be used
+ * @get_event_state: optional method to retrieve state of single event
+ * @set_event_state: optional method to alter state of single event
* @ff: force feedback structure associated with the device if device
* supports force feedback effects
* @repeat_key: stores key code of the last key pressed; used to implement
@@ -1095,6 +1131,10 @@ struct input_dev {
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
+ int (*get_event_state)(struct input_dev *dev,
+ struct input_event_state *st);
+ int (*set_event_state)(struct input_dev *dev,
+ const struct input_event_state *st);
struct ff_device *ff;
@@ -1357,6 +1397,10 @@ static inline void input_set_abs_params(struct input_dev *dev, int axis, int min
int input_get_keycode(struct input_dev *dev, int scancode, int *keycode);
int input_set_keycode(struct input_dev *dev, int scancode, int keycode);
+int input_get_event_state(struct input_dev *dev,
+ struct input_event_state *st);
+int input_set_event_state(struct input_dev *dev,
+ const struct input_event_state *st);
extern struct class input_class;