Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/input-mt.c
15109 views
1
/*
2
* Input Multitouch Library
3
*
4
* Copyright (c) 2008-2010 Henrik Rydberg
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 as published by
8
* the Free Software Foundation.
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
* input_mt_init_slots() - initialize MT input slots
18
* @dev: input device supporting MT events and finger tracking
19
* @num_slots: number of slots used by the device
20
*
21
* This function allocates all necessary memory for MT slot handling
22
* in the input device, prepares the ABS_MT_SLOT and
23
* ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
24
* May be called repeatedly. Returns -EINVAL if attempting to
25
* reinitialize with a different number of slots.
26
*/
27
int 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
/* Mark slots as 'unused' */
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
}
51
EXPORT_SYMBOL(input_mt_init_slots);
52
53
/**
54
* input_mt_destroy_slots() - frees the MT slots of the input device
55
* @dev: input device with allocated MT slots
56
*
57
* This function is only needed in error path as the input core will
58
* automatically free the MT slots when the device is destroyed.
59
*/
60
void 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
}
68
EXPORT_SYMBOL(input_mt_destroy_slots);
69
70
/**
71
* input_mt_report_slot_state() - report contact state
72
* @dev: input device with allocated MT slots
73
* @tool_type: the tool type to use in this slot
74
* @active: true if contact is active, false otherwise
75
*
76
* Reports a contact via ABS_MT_TRACKING_ID, and optionally
77
* ABS_MT_TOOL_TYPE. If active is true and the slot is currently
78
* inactive, or if the tool type is changed, a new tracking id is
79
* assigned to the slot. The tool type is only reported if the
80
* corresponding absbit field is set.
81
*/
82
void 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
}
101
EXPORT_SYMBOL(input_mt_report_slot_state);
102
103
/**
104
* input_mt_report_finger_count() - report contact count
105
* @dev: input device with allocated MT slots
106
* @count: the number of contacts
107
*
108
* Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
109
* BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP.
110
*
111
* The input core ensures only the KEY events already setup for
112
* this device will produce output.
113
*/
114
void 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
}
121
EXPORT_SYMBOL(input_mt_report_finger_count);
122
123
/**
124
* input_mt_report_pointer_emulation() - common pointer emulation
125
* @dev: input device with allocated MT slots
126
* @use_count: report number of active contacts as finger count
127
*
128
* Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and
129
* ABS_PRESSURE. Touchpad finger count is emulated if use_count is true.
130
*
131
* The input core ensures only the KEY and ABS axes already setup for
132
* this device will produce output.
133
*/
134
void 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
}
170
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
171
172