summary refs log tree commit diff
path: root/drivers/input
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-08-02 20:18:21 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-02 20:30:04 -0700
commitd31b2865a4e8a9dd02f39e56c8fadb824c5e187b (patch)
treecbe062757aa54c88c8e9ae2bf6ff87f791313c60 /drivers/input
parent987a6c0298260b7aa40702b349282554d6180e4b (diff)
downloadlinux-d31b2865a4e8a9dd02f39e56c8fadb824c5e187b.tar.gz
Input: dynamically allocate ABS information
As all callers are now changed to only use the input_abs_*() access
helpers, switching over to dynamically allocated ABS information is
easy. This reduces size of struct input_dev from 3152 to 1640 on
64 bit architectures.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-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 9807c8ff6a84..08f48c03eec4 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 7259adb8619d..a9b025f4147a 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);