aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-08-02 23:18:21 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-02 23:30:04 -0400
commitd31b2865a4e8a9dd02f39e56c8fadb824c5e187b (patch)
treecbe062757aa54c88c8e9ae2bf6ff87f791313c60
parent987a6c0298260b7aa40702b349282554d6180e4b (diff)
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>
-rw-r--r--drivers/input/evdev.c21
-rw-r--r--drivers/input/input.c42
-rw-r--r--include/linux/input.h57
3 files changed, 63 insertions, 57 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,
649 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { 649 if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
650 650
651 t = _IOC_NR(cmd) & ABS_MAX; 651 t = _IOC_NR(cmd) & ABS_MAX;
652 652 abs = dev->absinfo[t];
653 abs.value = input_abs_get_val(dev, t);
654 abs.minimum = input_abs_get_min(dev, t);
655 abs.maximum = input_abs_get_max(dev, t);
656 abs.fuzz = input_abs_get_fuzz(dev, t);
657 abs.flat = input_abs_get_flat(dev, t);
658 abs.resolution = input_abs_get_res(dev, t);
659 653
660 if (copy_to_user(p, &abs, min_t(size_t, 654 if (copy_to_user(p, &abs, min_t(size_t,
661 _IOC_SIZE(cmd), 655 _IOC_SIZE(cmd),
@@ -691,6 +685,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
691 sizeof(struct input_absinfo)))) 685 sizeof(struct input_absinfo))))
692 return -EFAULT; 686 return -EFAULT;
693 687
688 if (_IOC_SIZE(cmd) < sizeof(struct input_absinfo))
689 abs.resolution = 0;
690
694 /* We can't change number of reserved MT slots */ 691 /* We can't change number of reserved MT slots */
695 if (t == ABS_MT_SLOT) 692 if (t == ABS_MT_SLOT)
696 return -EINVAL; 693 return -EINVAL;
@@ -701,15 +698,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
701 * of event. 698 * of event.
702 */ 699 */
703 spin_lock_irq(&dev->event_lock); 700 spin_lock_irq(&dev->event_lock);
704 701 dev->absinfo[t] = abs;
705 input_abs_set_val(dev, t, abs.value);
706 input_abs_set_min(dev, t, abs.minimum);
707 input_abs_set_max(dev, t, abs.maximum);
708 input_abs_set_fuzz(dev, t, abs.fuzz);
709 input_abs_set_flat(dev, t, abs.flat);
710 input_abs_set_res(dev, t, _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
711 0 : abs.resolution);
712
713 spin_unlock_irq(&dev->event_lock); 702 spin_unlock_irq(&dev->event_lock);
714 703
715 return 0; 704 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,
182 is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST; 182 is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;
183 183
184 if (!is_mt_event) { 184 if (!is_mt_event) {
185 pold = &dev->abs[code]; 185 pold = &dev->absinfo[code].value;
186 } else if (dev->mt) { 186 } else if (dev->mt) {
187 struct input_mt_slot *mtslot = &dev->mt[dev->slot]; 187 struct input_mt_slot *mtslot = &dev->mt[dev->slot];
188 pold = &mtslot->abs[code - ABS_MT_FIRST]; 188 pold = &mtslot->abs[code - ABS_MT_FIRST];
@@ -196,7 +196,7 @@ static int input_handle_abs_event(struct input_dev *dev,
196 196
197 if (pold) { 197 if (pold) {
198 *pval = input_defuzz_abs_event(*pval, *pold, 198 *pval = input_defuzz_abs_event(*pval, *pold,
199 dev->absfuzz[code]); 199 dev->absinfo[code].fuzz);
200 if (*pold == *pval) 200 if (*pold == *pval)
201 return INPUT_IGNORE_EVENT; 201 return INPUT_IGNORE_EVENT;
202 202
@@ -391,6 +391,43 @@ void input_inject_event(struct input_handle *handle,
391EXPORT_SYMBOL(input_inject_event); 391EXPORT_SYMBOL(input_inject_event);
392 392
393/** 393/**
394 * input_alloc_absinfo - allocates array of input_absinfo structs
395 * @dev: the input device emitting absolute events
396 *
397 * If the absinfo struct the caller asked for is already allocated, this
398 * functions will not do anything.
399 */
400void input_alloc_absinfo(struct input_dev *dev)
401{
402 if (!dev->absinfo)
403 dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
404 GFP_KERNEL);
405
406 WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
407}
408EXPORT_SYMBOL(input_alloc_absinfo);
409
410void input_set_abs_params(struct input_dev *dev, unsigned int axis,
411 int min, int max, int fuzz, int flat)
412{
413 struct input_absinfo *absinfo;
414
415 input_alloc_absinfo(dev);
416 if (!dev->absinfo)
417 return;
418
419 absinfo = &dev->absinfo[axis];
420 absinfo->minimum = min;
421 absinfo->maximum = max;
422 absinfo->fuzz = fuzz;
423 absinfo->flat = flat;
424
425 dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
426}
427EXPORT_SYMBOL(input_set_abs_params);
428
429
430/**
394 * input_grab_device - grabs device for exclusive use 431 * input_grab_device - grabs device for exclusive use
395 * @handle: input handle that wants to own the device 432 * @handle: input handle that wants to own the device
396 * 433 *
@@ -1308,6 +1345,7 @@ static void input_dev_release(struct device *device)
1308 1345
1309 input_ff_destroy(dev); 1346 input_ff_destroy(dev);
1310 input_mt_destroy_slots(dev); 1347 input_mt_destroy_slots(dev);
1348 kfree(dev->absinfo);
1311 kfree(dev); 1349 kfree(dev);
1312 1350
1313 module_put(THIS_MODULE); 1351 module_put(THIS_MODULE);
diff --git a/include/linux/input.h b/include/linux/input.h
index 4a5531161de1..896a92227bc4 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -776,6 +776,7 @@ struct input_absinfo {
776#define REP_DELAY 0x00 776#define REP_DELAY 0x00
777#define REP_PERIOD 0x01 777#define REP_PERIOD 0x01
778#define REP_MAX 0x01 778#define REP_MAX 0x01
779#define REP_CNT (REP_MAX+1)
779 780
780/* 781/*
781 * Sounds 782 * Sounds
@@ -1099,21 +1100,18 @@ struct input_mt_slot {
1099 * @repeat_key: stores key code of the last key pressed; used to implement 1100 * @repeat_key: stores key code of the last key pressed; used to implement
1100 * software autorepeat 1101 * software autorepeat
1101 * @timer: timer for software autorepeat 1102 * @timer: timer for software autorepeat
1102 * @abs: current values for reports from absolute axes
1103 * @rep: current values for autorepeat parameters (delay, rate) 1103 * @rep: current values for autorepeat parameters (delay, rate)
1104 * @mt: pointer to array of struct input_mt_slot holding current values 1104 * @mt: pointer to array of struct input_mt_slot holding current values
1105 * of tracked contacts 1105 * of tracked contacts
1106 * @mtsize: number of MT slots the device uses 1106 * @mtsize: number of MT slots the device uses
1107 * @slot: MT slot currently being transmitted 1107 * @slot: MT slot currently being transmitted
1108 * @absinfo: array of &struct absinfo elements holding information
1109 * about absolute axes (current value, min, max, flat, fuzz,
1110 * resolution)
1108 * @key: reflects current state of device's keys/buttons 1111 * @key: reflects current state of device's keys/buttons
1109 * @led: reflects current state of device's LEDs 1112 * @led: reflects current state of device's LEDs
1110 * @snd: reflects current state of sound effects 1113 * @snd: reflects current state of sound effects
1111 * @sw: reflects current state of device's switches 1114 * @sw: reflects current state of device's switches
1112 * @absmax: maximum values for events coming from absolute axes
1113 * @absmin: minimum values for events coming from absolute axes
1114 * @absfuzz: describes noisiness for axes
1115 * @absflat: size of the center flat position (used by joydev)
1116 * @absres: resolution used for events coming form absolute axes
1117 * @open: this method is called when the very first user calls 1115 * @open: this method is called when the very first user calls
1118 * input_open_device(). The driver must prepare the device 1116 * input_open_device(). The driver must prepare the device
1119 * to start generating events (start polling thread, 1117 * to start generating events (start polling thread,
@@ -1180,24 +1178,19 @@ struct input_dev {
1180 unsigned int repeat_key; 1178 unsigned int repeat_key;
1181 struct timer_list timer; 1179 struct timer_list timer;
1182 1180
1183 int abs[ABS_CNT]; 1181 int rep[REP_CNT];
1184 int rep[REP_MAX + 1];
1185 1182
1186 struct input_mt_slot *mt; 1183 struct input_mt_slot *mt;
1187 int mtsize; 1184 int mtsize;
1188 int slot; 1185 int slot;
1189 1186
1187 struct input_absinfo *absinfo;
1188
1190 unsigned long key[BITS_TO_LONGS(KEY_CNT)]; 1189 unsigned long key[BITS_TO_LONGS(KEY_CNT)];
1191 unsigned long led[BITS_TO_LONGS(LED_CNT)]; 1190 unsigned long led[BITS_TO_LONGS(LED_CNT)];
1192 unsigned long snd[BITS_TO_LONGS(SND_CNT)]; 1191 unsigned long snd[BITS_TO_LONGS(SND_CNT)];
1193 unsigned long sw[BITS_TO_LONGS(SW_CNT)]; 1192 unsigned long sw[BITS_TO_LONGS(SW_CNT)];
1194 1193
1195 int absmax[ABS_CNT];
1196 int absmin[ABS_CNT];
1197 int absfuzz[ABS_CNT];
1198 int absflat[ABS_CNT];
1199 int absres[ABS_CNT];
1200
1201 int (*open)(struct input_dev *dev); 1194 int (*open)(struct input_dev *dev);
1202 void (*close)(struct input_dev *dev); 1195 void (*close)(struct input_dev *dev);
1203 int (*flush)(struct input_dev *dev, struct file *file); 1196 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
1459 dev->hint_events_per_packet = n_events; 1452 dev->hint_events_per_packet = n_events;
1460} 1453}
1461 1454
1462static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat) 1455void input_alloc_absinfo(struct input_dev *dev);
1463{ 1456void input_set_abs_params(struct input_dev *dev, unsigned int axis,
1464 dev->absmin[axis] = min; 1457 int min, int max, int fuzz, int flat);
1465 dev->absmax[axis] = max;
1466 dev->absfuzz[axis] = fuzz;
1467 dev->absflat[axis] = flat;
1468
1469 dev->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
1470}
1471 1458
1472#define INPUT_GENERATE_ABS_ACCESSORS(_suffix, _item) \ 1459#define INPUT_GENERATE_ABS_ACCESSORS(_suffix, _item) \
1473static inline int input_abs_get_##_suffix(struct input_dev *dev, \ 1460static inline int input_abs_get_##_suffix(struct input_dev *dev, \
1474 unsigned int axis) \ 1461 unsigned int axis) \
1475{ \ 1462{ \
1476 return dev->abs##_item[axis]; \ 1463 return dev->absinfo ? dev->absinfo[axis]._item : 0; \
1477} \ 1464} \
1478 \ 1465 \
1479static inline void input_abs_set_##_suffix(struct input_dev *dev, \ 1466static inline void input_abs_set_##_suffix(struct input_dev *dev, \
1480 unsigned int axis, int val) \ 1467 unsigned int axis, int val) \
1481{ \ 1468{ \
1482 dev->abs##_item[axis] = val; \ 1469 input_alloc_absinfo(dev); \
1470 if (dev->absinfo) \
1471 dev->absinfo[axis]._item = val; \
1483} 1472}
1484 1473
1485INPUT_GENERATE_ABS_ACCESSORS(min, min) 1474INPUT_GENERATE_ABS_ACCESSORS(val, value)
1486INPUT_GENERATE_ABS_ACCESSORS(max, max) 1475INPUT_GENERATE_ABS_ACCESSORS(min, minimum)
1476INPUT_GENERATE_ABS_ACCESSORS(max, maximum)
1487INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz) 1477INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
1488INPUT_GENERATE_ABS_ACCESSORS(flat, flat) 1478INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
1489INPUT_GENERATE_ABS_ACCESSORS(res, res) 1479INPUT_GENERATE_ABS_ACCESSORS(res, resolution)
1490
1491static inline int input_abs_get_val(struct input_dev *dev, unsigned int axis)
1492{
1493 return dev->abs[axis];
1494}
1495
1496static inline void input_abs_set_val(struct input_dev *dev,
1497 unsigned int axis, int val)
1498{
1499 dev->abs[axis] = val;
1500}
1501 1480
1502int input_get_keycode(struct input_dev *dev, 1481int input_get_keycode(struct input_dev *dev,
1503 unsigned int scancode, unsigned int *keycode); 1482 unsigned int scancode, unsigned int *keycode);