mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
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>
This commit is contained in:
parent
987a6c0298
commit
d31b2865a4
3 changed files with 63 additions and 57 deletions
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue