1
2
3
4
5
6
7
8
9
10
11#include <linux/input/mt.h>
12#include <linux/slab.h>
13
14#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
15
16
17
18
19
20
21
22
23
24
25
26
27int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
28{
29 int i;
30
31 if (!num_slots)
32 return 0;
33 if (dev->mt)
34 return dev->mtsize != num_slots ? -EINVAL : 0;
35
36 dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
37 if (!dev->mt)
38 return -ENOMEM;
39
40 dev->mtsize = num_slots;
41 input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
42 input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
43 input_set_events_per_packet(dev, 6 * num_slots);
44
45
46 for (i = 0; i < num_slots; i++)
47 input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
48
49 return 0;
50}
51EXPORT_SYMBOL(input_mt_init_slots);
52
53
54
55
56
57
58
59
60void input_mt_destroy_slots(struct input_dev *dev)
61{
62 kfree(dev->mt);
63 dev->mt = NULL;
64 dev->mtsize = 0;
65 dev->slot = 0;
66 dev->trkid = 0;
67}
68EXPORT_SYMBOL(input_mt_destroy_slots);
69
70
71
72
73
74
75
76
77
78
79
80
81
82void input_mt_report_slot_state(struct input_dev *dev,
83 unsigned int tool_type, bool active)
84{
85 struct input_mt_slot *mt;
86 int id;
87
88 if (!dev->mt || !active) {
89 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
90 return;
91 }
92
93 mt = &dev->mt[dev->slot];
94 id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
95 if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
96 id = input_mt_new_trkid(dev);
97
98 input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
99 input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
100}
101EXPORT_SYMBOL(input_mt_report_slot_state);
102
103
104
105
106
107
108
109
110
111
112
113
114void input_mt_report_finger_count(struct input_dev *dev, int count)
115{
116 input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1);
117 input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2);
118 input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3);
119 input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4);
120}
121EXPORT_SYMBOL(input_mt_report_finger_count);
122
123
124
125
126
127
128
129
130
131
132
133
134void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
135{
136 struct input_mt_slot *oldest = 0;
137 int oldid = dev->trkid;
138 int count = 0;
139 int i;
140
141 for (i = 0; i < dev->mtsize; ++i) {
142 struct input_mt_slot *ps = &dev->mt[i];
143 int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
144
145 if (id < 0)
146 continue;
147 if ((id - oldid) & TRKID_SGN) {
148 oldest = ps;
149 oldid = id;
150 }
151 count++;
152 }
153
154 input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
155 if (use_count)
156 input_mt_report_finger_count(dev, count);
157
158 if (oldest) {
159 int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
160 int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
161 int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
162
163 input_event(dev, EV_ABS, ABS_X, x);
164 input_event(dev, EV_ABS, ABS_Y, y);
165 input_event(dev, EV_ABS, ABS_PRESSURE, p);
166 } else {
167 input_event(dev, EV_ABS, ABS_PRESSURE, 0);
168 }
169}
170EXPORT_SYMBOL(input_mt_report_pointer_emulation);
171