summaryrefslogtreecommitdiff
path: root/usr/src/dkms_source_tree/input-mt.h
blob: e53d274f4275370ba640b59eb6b8b9cee9763680 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef _INPUT_MT_LOCAL_H
#define _INPUT_MT_LOCAL_H

/*
 * Input Multitouch Library
 *
 * Copyright (c) 2010 Henrik Rydberg
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */

#include <linux/version.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)

#include <linux/input/mt.h>

#else

#include <linux/input.h>

#define MT_TOOL_MAX		1

#define TRKID_MAX	0xffff
#define TRKID_SGN	((TRKID_MAX + 1) >> 1)

static int trkid;

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

static inline void input_mt_set_value(struct input_mt_slot *slot,
				      unsigned code, int value)
{
	slot->abs[code - ABS_MT_FIRST] = value;
}

static inline int input_mt_get_value(const struct input_mt_slot *slot,
				     unsigned code)
{
	return slot->abs[code - ABS_MT_FIRST];
}

static inline int input_mt_new_trkid(struct input_dev *dev)
{
	return trkid++ & TRKID_MAX;
}

/**
 * input_mt_init_slots() - initialize 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, prepares the ABS_MT_SLOT and
 * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
 * May be called repeatedly. Returns -EINVAL if attempting to
 * reinitialize with a different number of slots.
 */
static int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
{
	int ret;

	if (dev->mt)
		return dev->mtsize != num_slots ? -EINVAL : 0;

	ret = input_mt_create_slots(dev, num_slots);
	if (ret)
		return ret;

	input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
	input_set_events_per_packet(dev, 6 * num_slots);

	return 0;
}

/**
 * input_mt_report_state() - report contact state
 * @dev: input device with allocated MT slots
 * @active: true if contact is active, false otherwise
 *
 * Reports an active touch via ABS_MT_TRACKING_ID. If active is
 * true and the slot is currently inactive, a new tracking id is
 * assigned to the slot.
 */
static void input_mt_report_slot_state(struct input_dev *dev, unsigned type,
				       bool active)
{
	struct input_mt_slot *mt = dev->mt;
	int id;

	if (!mt || !active) {
		input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
		return;
	}

	id = input_mt_get_value(&mt[dev->slot], ABS_MT_TRACKING_ID);
	if (id < 0)
		id = input_mt_new_trkid(dev);
	input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
}

/**
 * input_mt_report_pointer_emulation() - common pointer emulation
 * @dev: input device with allocated MT slots
 *
 * Performs legacy pointer emulation via BTN_TOUCH.
 */
static void input_mt_report_pointer_emulation(struct input_dev *dev, bool more)
{
	struct input_mt_slot *oldest = 0;
	int oldid = trkid;
	int count = 0;
	int i;

	for (i = 0; i < dev->mtsize; ++i) {
		struct input_mt_slot *ps = &dev->mt[i];
		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);

		if (id < 0)
			continue;
		if ((id - oldid) & TRKID_SGN) {
			oldest = ps;
			oldid = id;
		}
		count++;
	}

	input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
	input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
	input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
	input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
	input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count > 3);

	if (oldest) {
		int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
		int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
		int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);

		input_event(dev, EV_ABS, ABS_X, x);
		input_event(dev, EV_ABS, ABS_Y, y);
		input_event(dev, EV_ABS, ABS_PRESSURE, p);
	} else {
		input_event(dev, EV_ABS, ABS_PRESSURE, 0);
	}
}

#endif

#endif