Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d31b2865 authored by Daniel Mack's avatar Daniel Mack Committed by Dmitry Torokhov
Browse files

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: default avatarDaniel Mack <daniel@caiaq.de>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 987a6c02
Loading
Loading
Loading
Loading
+5 −16
Original line number Original line Diff line number Diff line
@@ -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))) {
			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {


				t = _IOC_NR(cmd) & ABS_MAX;
				t = _IOC_NR(cmd) & ABS_MAX;

				abs = dev->absinfo[t];
				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);


				if (copy_to_user(p, &abs, min_t(size_t,
				if (copy_to_user(p, &abs, min_t(size_t,
								_IOC_SIZE(cmd),
								_IOC_SIZE(cmd),
@@ -691,6 +685,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
								  sizeof(struct input_absinfo))))
								  sizeof(struct input_absinfo))))
					return -EFAULT;
					return -EFAULT;


				if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
					abs.resolution = 0;

				/* We can't change number of reserved MT slots */
				/* We can't change number of reserved MT slots */
				if (t == ABS_MT_SLOT)
				if (t == ABS_MT_SLOT)
					return -EINVAL;
					return -EINVAL;
@@ -701,15 +698,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
				 * of event.
				 * of event.
				 */
				 */
				spin_lock_irq(&dev->event_lock);
				spin_lock_irq(&dev->event_lock);

				dev->absinfo[t] = abs;
				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);

				spin_unlock_irq(&dev->event_lock);
				spin_unlock_irq(&dev->event_lock);


				return 0;
				return 0;
+40 −2
Original line number Original line Diff line number Diff line
@@ -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;
	is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;


	if (!is_mt_event) {
	if (!is_mt_event) {
		pold = &dev->abs[code];
		pold = &dev->absinfo[code].value;
	} else if (dev->mt) {
	} else if (dev->mt) {
		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
		pold = &mtslot->abs[code - ABS_MT_FIRST];
		pold = &mtslot->abs[code - ABS_MT_FIRST];
@@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev,


	if (pold) {
	if (pold) {
		*pval = input_defuzz_abs_event(*pval, *pold,
		*pval = input_defuzz_abs_event(*pval, *pold,
						dev->absfuzz[code]);
						dev->absinfo[code].fuzz);
		if (*pold == *pval)
		if (*pold == *pval)
			return INPUT_IGNORE_EVENT;
			return INPUT_IGNORE_EVENT;


@@ -390,6 +390,43 @@ void input_inject_event(struct input_handle *handle,
}
}
EXPORT_SYMBOL(input_inject_event);
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
 * input_grab_device - grabs device for exclusive use
 * @handle: input handle that wants to own the device
 * @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_ff_destroy(dev);
	input_mt_destroy_slots(dev);
	input_mt_destroy_slots(dev);
	kfree(dev->absinfo);
	kfree(dev);
	kfree(dev);


	module_put(THIS_MODULE);
	module_put(THIS_MODULE);
+18 −39
Original line number Original line Diff line number Diff line
@@ -776,6 +776,7 @@ struct input_absinfo {
#define REP_DELAY		0x00
#define REP_DELAY		0x00
#define REP_PERIOD		0x01
#define REP_PERIOD		0x01
#define REP_MAX			0x01
#define REP_MAX			0x01
#define REP_CNT			(REP_MAX+1)


/*
/*
 * Sounds
 * Sounds
@@ -1099,21 +1100,18 @@ struct input_mt_slot {
 * @repeat_key: stores key code of the last key pressed; used to implement
 * @repeat_key: stores key code of the last key pressed; used to implement
 *	software autorepeat
 *	software autorepeat
 * @timer: timer for software autorepeat
 * @timer: timer for software autorepeat
 * @abs: current values for reports from absolute axes
 * @rep: current values for autorepeat parameters (delay, rate)
 * @rep: current values for autorepeat parameters (delay, rate)
 * @mt: pointer to array of struct input_mt_slot holding current values
 * @mt: pointer to array of struct input_mt_slot holding current values
 *	of tracked contacts
 *	of tracked contacts
 * @mtsize: number of MT slots the device uses
 * @mtsize: number of MT slots the device uses
 * @slot: MT slot currently being transmitted
 * @slot: MT slot currently being transmitted
 * @absinfo: array of &struct absinfo elements holding information
 *	about absolute axes (current value, min, max, flat, fuzz,
 *	resolution)
 * @key: reflects current state of device's keys/buttons
 * @key: reflects current state of device's keys/buttons
 * @led: reflects current state of device's LEDs
 * @led: reflects current state of device's LEDs
 * @snd: reflects current state of sound effects
 * @snd: reflects current state of sound effects
 * @sw: reflects current state of device's switches
 * @sw: reflects current state of device's switches
 * @absmax: maximum values for events coming from absolute axes
 * @absmin: minimum values for events coming from absolute axes
 * @absfuzz: describes noisiness for axes
 * @absflat: size of the center flat position (used by joydev)
 * @absres: resolution used for events coming form absolute axes
 * @open: this method is called when the very first user calls
 * @open: this method is called when the very first user calls
 *	input_open_device(). The driver must prepare the device
 *	input_open_device(). The driver must prepare the device
 *	to start generating events (start polling thread,
 *	to start generating events (start polling thread,
@@ -1180,24 +1178,19 @@ struct input_dev {
	unsigned int repeat_key;
	unsigned int repeat_key;
	struct timer_list timer;
	struct timer_list timer;


	int abs[ABS_CNT];
	int rep[REP_CNT];
	int rep[REP_MAX + 1];


	struct input_mt_slot *mt;
	struct input_mt_slot *mt;
	int mtsize;
	int mtsize;
	int slot;
	int slot;


	struct input_absinfo *absinfo;

	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
	unsigned long led[BITS_TO_LONGS(LED_CNT)];
	unsigned long led[BITS_TO_LONGS(LED_CNT)];
	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
	unsigned long sw[BITS_TO_LONGS(SW_CNT)];
	unsigned long sw[BITS_TO_LONGS(SW_CNT)];


	int absmax[ABS_CNT];
	int absmin[ABS_CNT];
	int absfuzz[ABS_CNT];
	int absflat[ABS_CNT];
	int absres[ABS_CNT];

	int (*open)(struct input_dev *dev);
	int (*open)(struct input_dev *dev);
	void (*close)(struct input_dev *dev);
	void (*close)(struct input_dev *dev);
	int (*flush)(struct input_dev *dev, struct file *file);
	int (*flush)(struct input_dev *dev, struct file *file);
@@ -1459,45 +1452,31 @@ static inline void input_set_events_per_packet(struct input_dev *dev, int n_even
	dev->hint_events_per_packet = n_events;
	dev->hint_events_per_packet = n_events;
}
}


static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
void input_alloc_absinfo(struct input_dev *dev);
{
void input_set_abs_params(struct input_dev *dev, unsigned int axis,
	dev->absmin[axis] = min;
			  int min, int max, int fuzz, int flat);
	dev->absmax[axis] = max;
	dev->absfuzz[axis] = fuzz;
	dev->absflat[axis] = flat;

	dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
}


#define INPUT_GENERATE_ABS_ACCESSORS(_suffix, _item)			\
#define INPUT_GENERATE_ABS_ACCESSORS(_suffix, _item)			\
static inline int input_abs_get_##_suffix(struct input_dev *dev,	\
static inline int input_abs_get_##_suffix(struct input_dev *dev,	\
					  unsigned int axis)		\
					  unsigned int axis)		\
{									\
{									\
	return dev->abs##_item[axis];					\
	return dev->absinfo ? dev->absinfo[axis]._item : 0;		\
}									\
}									\
									\
									\
static inline void input_abs_set_##_suffix(struct input_dev *dev,	\
static inline void input_abs_set_##_suffix(struct input_dev *dev,	\
					   unsigned int axis, int val)	\
					   unsigned int axis, int val)	\
{									\
{									\
	dev->abs##_item[axis] = val;					\
	input_alloc_absinfo(dev);					\
	if (dev->absinfo)						\
		dev->absinfo[axis]._item = val;				\
}
}


INPUT_GENERATE_ABS_ACCESSORS(min, min)
INPUT_GENERATE_ABS_ACCESSORS(val, value)
INPUT_GENERATE_ABS_ACCESSORS(max, max)
INPUT_GENERATE_ABS_ACCESSORS(min, minimum)
INPUT_GENERATE_ABS_ACCESSORS(max, maximum)
INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
INPUT_GENERATE_ABS_ACCESSORS(res, res)
INPUT_GENERATE_ABS_ACCESSORS(res, resolution)

static inline int input_abs_get_val(struct input_dev *dev, unsigned int axis)
{
	return dev->abs[axis];
}

static inline void input_abs_set_val(struct input_dev *dev,
				     unsigned int axis, int val)
{
	dev->abs[axis] = val;
}


int input_get_keycode(struct input_dev *dev,
int input_get_keycode(struct input_dev *dev,
		      unsigned int scancode, unsigned int *keycode);
		      unsigned int scancode, unsigned int *keycode);