summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/evdev.c21
-rw-r--r--drivers/input/input.c42
2 files changed, 45 insertions, 18 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9807c8ff6a8..08f48c03eec 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -649,13 +649,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
t = _IOC_NR(cmd) & ABS_MAX;
-
- abs.value = input_abs_get_val(dev, t);
- abs.minimum = input_abs_get_min(dev, t);
- abs.maximum = input_abs_get_max(dev, t);
- abs.fuzz = input_abs_get_fuzz(dev, t);
- abs.flat = input_abs_get_flat(dev, t);
- abs.resolution = input_abs_get_res(dev, t);
+ abs = dev->absinfo[t];
if (copy_to_user(p, &abs, min_t(size_t,
_IOC_SIZE(cmd),
@@ -691,6 +685,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
sizeof(struct input_absinfo))))
return -EFAULT;
+ if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
+ abs.resolution = 0;
+
/* We can't change number of reserved MT slots */
if (t == ABS_MT_SLOT)
return -EINVAL;
@@ -701,15 +698,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
* of event.
*/
spin_lock_irq(&dev->event_lock);
-
- input_abs_set_val(dev, t, abs.value);
- input_abs_set_min(dev, t, abs.minimum);
- input_abs_set_max(dev, t, abs.maximum);
- input_abs_set_fuzz(dev, t, abs.fuzz);
- input_abs_set_flat(dev, t, abs.flat);
- input_abs_set_res(dev, t, _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
- 0 : abs.resolution);
-
+ dev->absinfo[t] = abs;
spin_unlock_irq(&dev->event_lock);
return 0;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7259adb8619..a9b025f4147 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -182,7 +182,7 @@ static int input_handle_abs_event(struct input_dev *dev,
is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
if (!is_mt_event) {
- pold = &dev->abs[code];
+ pold = &dev->absinfo[code].value;
} else if (dev->mt) {
struct input_mt_slot *mtslot = &dev->mt[dev->slot];
pold = &mtslot->abs[code - ABS_MT_FIRST];
@@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev,
if (pold) {
*pval = input_defuzz_abs_event(*pval, *pold,
- dev->absfuzz[code]);
+ dev->absinfo[code].fuzz);
if (*pold == *pval)
return INPUT_IGNORE_EVENT;
@@ -391,6 +391,43 @@ void input_inject_event(struct input_handle *handle,
EXPORT_SYMBOL(input_inject_event);
/**
+ * input_alloc_absinfo - allocates array of input_absinfo structs
+ * @dev: the input device emitting absolute events
+ *
+ * If the absinfo struct the caller asked for is already allocated, this
+ * functions will not do anything.
+ */
+void input_alloc_absinfo(struct input_dev *dev)
+{
+ if (!dev->absinfo)
+ dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
+ GFP_KERNEL);
+
+ WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
+}
+EXPORT_SYMBOL(input_alloc_absinfo);
+
+void input_set_abs_params(struct input_dev *dev, unsigned int axis,
+ int min, int max, int fuzz, int flat)
+{
+ struct input_absinfo *absinfo;
+
+ input_alloc_absinfo(dev);
+ if (!dev->absinfo)
+ return;
+
+ absinfo = &dev->absinfo[axis];
+ absinfo->minimum = min;
+ absinfo->maximum = max;
+ absinfo->fuzz = fuzz;
+ absinfo->flat = flat;
+
+ dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
+}
+EXPORT_SYMBOL(input_set_abs_params);
+
+
+/**
* input_grab_device - grabs device for exclusive use
* @handle: input handle that wants to own the device
*
@@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device)
input_ff_destroy(dev);
input_mt_destroy_slots(dev);
+ kfree(dev->absinfo);
kfree(dev);
module_put(THIS_MODULE);