aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/input/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r--drivers/input/input.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c3139bc2aa0d..e5a668ce884d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -47,6 +47,17 @@ static DEFINE_MUTEX(input_mutex);
static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
+static const unsigned int input_max_code[EV_CNT] = {
+ [EV_KEY] = KEY_MAX,
+ [EV_REL] = REL_MAX,
+ [EV_ABS] = ABS_MAX,
+ [EV_MSC] = MSC_MAX,
+ [EV_SW] = SW_MAX,
+ [EV_LED] = LED_MAX,
+ [EV_SND] = SND_MAX,
+ [EV_FF] = FF_MAX,
+};
+
static inline int is_event_supported(unsigned int code,
unsigned long *bm, unsigned int max)
{
@@ -511,6 +522,9 @@ void input_set_abs_params(struct input_dev *dev, unsigned int axis,
{
struct input_absinfo *absinfo;
+ __set_bit(EV_ABS, dev->evbit);
+ __set_bit(axis, dev->absbit);
+
input_alloc_absinfo(dev);
if (!dev->absinfo)
return;
@@ -520,12 +534,45 @@ void input_set_abs_params(struct input_dev *dev, unsigned int axis,
absinfo->maximum = max;
absinfo->fuzz = fuzz;
absinfo->flat = flat;
-
- __set_bit(EV_ABS, dev->evbit);
- __set_bit(axis, dev->absbit);
}
EXPORT_SYMBOL(input_set_abs_params);
+/**
+ * input_copy_abs - Copy absinfo from one input_dev to another
+ * @dst: Destination input device to copy the abs settings to
+ * @dst_axis: ABS_* value selecting the destination axis
+ * @src: Source input device to copy the abs settings from
+ * @src_axis: ABS_* value selecting the source axis
+ *
+ * Set absinfo for the selected destination axis by copying it from
+ * the specified source input device's source axis.
+ * This is useful to e.g. setup a pen/stylus input-device for combined
+ * touchscreen/pen hardware where the pen uses the same coordinates as
+ * the touchscreen.
+ */
+void input_copy_abs(struct input_dev *dst, unsigned int dst_axis,
+ const struct input_dev *src, unsigned int src_axis)
+{
+ /* src must have EV_ABS and src_axis set */
+ if (WARN_ON(!(test_bit(EV_ABS, src->evbit) &&
+ test_bit(src_axis, src->absbit))))
+ return;
+
+ /*
+ * input_alloc_absinfo() may have failed for the source. Our caller is
+ * expected to catch this when registering the input devices, which may
+ * happen after the input_copy_abs() call.
+ */
+ if (!src->absinfo)
+ return;
+
+ input_set_capability(dst, EV_ABS, dst_axis);
+ if (!dst->absinfo)
+ return;
+
+ dst->absinfo[dst_axis] = src->absinfo[src_axis];
+}
+EXPORT_SYMBOL(input_copy_abs);
/**
* input_grab_device - grabs device for exclusive use
@@ -2074,6 +2121,14 @@ EXPORT_SYMBOL(input_get_timestamp);
*/
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
{
+ if (type < EV_CNT && input_max_code[type] &&
+ code > input_max_code[type]) {
+ pr_err("%s: invalid code %u for type %u\n", __func__, code,
+ type);
+ dump_stack();
+ return;
+ }
+
switch (type) {
case EV_KEY:
__set_bit(code, dev->keybit);
@@ -2085,9 +2140,6 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
case EV_ABS:
input_alloc_absinfo(dev);
- if (!dev->absinfo)
- return;
-
__set_bit(code, dev->absbit);
break;
@@ -2285,12 +2337,6 @@ int input_register_device(struct input_dev *dev)
/* KEY_RESERVED is not supposed to be transmitted to userspace. */
__clear_bit(KEY_RESERVED, dev->keybit);
- /* Buttonpads should not map BTN_RIGHT and/or BTN_MIDDLE. */
- if (test_bit(INPUT_PROP_BUTTONPAD, dev->propbit)) {
- __clear_bit(BTN_RIGHT, dev->keybit);
- __clear_bit(BTN_MIDDLE, dev->keybit);
- }
-
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev);