Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202214
b: refs/heads/master
c: 40d007e
h: refs/heads/master
v: v3
  • Loading branch information
Henrik Rydberg authored and Dmitry Torokhov committed Jul 16, 2010
1 parent 63bb337 commit 44d8a49
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 44 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a8aef622929bbba4d89498fb41dd445c14fae1f7
refs/heads/master: 40d007e7df1dab17bf1ecf91e718218354d963d7
4 changes: 4 additions & 0 deletions trunk/drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
sizeof(struct input_absinfo))))
return -EFAULT;

/* We can't change number of reserved MT slots */
if (t == ABS_MT_SLOT)
return -EINVAL;

/*
* Take event lock to ensure that we are not
* changing device parameters in the middle
Expand Down
135 changes: 92 additions & 43 deletions trunk/drivers/input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,6 @@ MODULE_LICENSE("GPL");

#define INPUT_DEVICES 256

/*
* EV_ABS events which should not be cached are listed here.
*/
static unsigned int input_abs_bypass_init_data[] __initdata = {
ABS_MT_TOUCH_MAJOR,
ABS_MT_TOUCH_MINOR,
ABS_MT_WIDTH_MAJOR,
ABS_MT_WIDTH_MINOR,
ABS_MT_ORIENTATION,
ABS_MT_POSITION_X,
ABS_MT_POSITION_Y,
ABS_MT_TOOL_TYPE,
ABS_MT_BLOB_ID,
ABS_MT_TRACKING_ID,
ABS_MT_PRESSURE,
0
};
static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];

static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);

Expand Down Expand Up @@ -181,6 +162,56 @@ static void input_stop_autorepeat(struct input_dev *dev)
#define INPUT_PASS_TO_DEVICE 2
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)

static int input_handle_abs_event(struct input_dev *dev,
unsigned int code, int *pval)
{
bool is_mt_event;
int *pold;

if (code == ABS_MT_SLOT) {
/*
* "Stage" the event; we'll flush it later, when we
* get actiual touch data.
*/
if (*pval >= 0 && *pval < dev->mtsize)
dev->slot = *pval;

return INPUT_IGNORE_EVENT;
}

is_mt_event = code >= ABS_MT_FIRST && code <= ABS_MT_LAST;

if (!is_mt_event) {
pold = &dev->abs[code];
} else if (dev->mt) {
struct input_mt_slot *mtslot = &dev->mt[dev->slot];
pold = &mtslot->abs[code - ABS_MT_FIRST];
} else {
/*
* Bypass filtering for multitouch events when
* not employing slots.
*/
pold = NULL;
}

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

*pold = *pval;
}

/* Flush pending "slot" event */
if (is_mt_event && dev->slot != dev->abs[ABS_MT_SLOT]) {
dev->abs[ABS_MT_SLOT] = dev->slot;
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
}

return INPUT_PASS_TO_HANDLERS;
}

static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
Expand Down Expand Up @@ -233,21 +264,9 @@ static void input_handle_event(struct input_dev *dev,
break;

case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) {

if (test_bit(code, input_abs_bypass)) {
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value);

value = input_defuzz_abs_event(value,
dev->abs[code], dev->absfuzz[code]);

if (dev->abs[code] != value) {
dev->abs[code] = value;
disposition = INPUT_PASS_TO_HANDLERS;
}
}
break;

case EV_REL:
Expand Down Expand Up @@ -1288,6 +1307,7 @@ static void input_dev_release(struct device *device)
struct input_dev *dev = to_input_dev(device);

input_ff_destroy(dev);
input_mt_destroy_slots(dev);
kfree(dev);

module_put(THIS_MODULE);
Expand Down Expand Up @@ -1536,6 +1556,45 @@ void input_free_device(struct input_dev *dev)
}
EXPORT_SYMBOL(input_free_device);

/**
* input_mt_create_slots() - create MT input slots
* @dev: input device supporting MT events and finger tracking
* @num_slots: number of slots used by the device
*
* This function allocates all necessary memory for MT slot handling
* in the input device, and adds ABS_MT_SLOT to the device capabilities.
*/
int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
{
if (!num_slots)
return 0;

dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
if (!dev->mt)
return -ENOMEM;

dev->mtsize = num_slots;
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);

return 0;
}
EXPORT_SYMBOL(input_mt_create_slots);

/**
* input_mt_destroy_slots() - frees the MT slots of the input device
* @dev: input device with allocated MT slots
*
* This function is only needed in error path as the input core will
* automatically free the MT slots when the device is destroyed.
*/
void input_mt_destroy_slots(struct input_dev *dev)
{
kfree(dev->mt);
dev->mt = NULL;
dev->mtsize = 0;
}
EXPORT_SYMBOL(input_mt_destroy_slots);

/**
* input_set_capability - mark device as capable of a certain event
* @dev: device that is capable of emitting or accepting event
Expand Down Expand Up @@ -1945,20 +2004,10 @@ static const struct file_operations input_fops = {
.open = input_open_file,
};

static void __init input_init_abs_bypass(void)
{
const unsigned int *p;

for (p = input_abs_bypass_init_data; *p; p++)
input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
}

static int __init input_init(void)
{
int err;

input_init_abs_bypass();

err = class_register(&input_class);
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
Expand Down
33 changes: 33 additions & 0 deletions trunk/include/linux/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,12 @@ struct input_absinfo {
#define ABS_TILT_X 0x1a
#define ABS_TILT_Y 0x1b
#define ABS_TOOL_WIDTH 0x1c

#define ABS_VOLUME 0x20

#define ABS_MISC 0x28

#define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
Expand All @@ -706,6 +709,12 @@ struct input_absinfo {
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */

#ifdef __KERNEL__
/* Implementation details, userspace should not care about these */
#define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
#define ABS_MT_LAST ABS_MT_PRESSURE
#endif

#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)

Expand Down Expand Up @@ -1047,6 +1056,14 @@ struct ff_effect {
#include <linux/timer.h>
#include <linux/mod_devicetable.h>

/**
* struct input_mt_slot - represents the state of an input MT slot
* @abs: holds current values of ABS_MT axes for this slot
*/
struct input_mt_slot {
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
};

/**
* struct input_dev - represents an input device
* @name: name of the device
Expand Down Expand Up @@ -1085,6 +1102,10 @@ struct ff_effect {
* @sync: set to 1 when there were no new events since last EV_SYNC
* @abs: current values for reports from absolute axes
* @rep: current values for autorepeat parameters (delay, rate)
* @mt: pointer to array of struct input_mt_slot holding current values
* of tracked contacts
* @mtsize: number of MT slots the device uses
* @slot: MT slot currently being transmitted
* @key: reflects current state of device's keys/buttons
* @led: reflects current state of device's LEDs
* @snd: reflects current state of sound effects
Expand Down Expand Up @@ -1164,6 +1185,10 @@ struct input_dev {
int abs[ABS_CNT];
int rep[REP_MAX + 1];

struct input_mt_slot *mt;
int mtsize;
int slot;

unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
Expand Down Expand Up @@ -1412,6 +1437,11 @@ static inline void input_mt_sync(struct input_dev *dev)
input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
}

static inline void input_mt_slot(struct input_dev *dev, int slot)
{
input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
}

void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);

/**
Expand Down Expand Up @@ -1506,5 +1536,8 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
int input_ff_create_memless(struct input_dev *dev, void *data,
int (*play_effect)(struct input_dev *, void *, struct ff_effect *));

int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots);
void input_mt_destroy_slots(struct input_dev *dev);

#endif
#endif

0 comments on commit 44d8a49

Please sign in to comment.