blob: 883d6d43006555f6f635f8755747b69cd12a2cee [file] [log] [blame]
Tim Kilbourn73475a42015-02-13 10:35:20 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputDevice"
18#define LOG_NDEBUG 0
19
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070020// Enables debug output for processing input events
21#define DEBUG_INPUT_EVENTS 0
22
Tim Kilbourn73475a42015-02-13 10:35:20 -080023#include <linux/input.h>
24
25#define __STDC_FORMAT_MACROS
26#include <cinttypes>
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070027#include <cstdlib>
Tim Kilbourn73475a42015-02-13 10:35:20 -080028#include <string>
29
30#include <utils/Log.h>
31#include <utils/Timers.h>
32
33#include "InputHub.h"
34#include "InputDevice.h"
35
36#define MSC_ANDROID_TIME_SEC 0x6
37#define MSC_ANDROID_TIME_USEC 0x7
38
39namespace android {
40
Tim Kilbourn3186e7b2015-04-16 15:32:08 -070041static InputBus getInputBus(const std::shared_ptr<InputDeviceNode>& node) {
42 switch (node->getBusType()) {
43 case BUS_USB:
44 return INPUT_BUS_USB;
45 case BUS_BLUETOOTH:
46 return INPUT_BUS_BT;
47 case BUS_RS232:
48 return INPUT_BUS_SERIAL;
49 default:
50 // TODO: check for other linux bus types that might not be built-in
51 return INPUT_BUS_BUILTIN;
52 }
53}
54
55static uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
56 // Touch devices get dibs on touch-related axes.
57 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
58 switch (axis) {
59 case ABS_X:
60 case ABS_Y:
61 case ABS_PRESSURE:
62 case ABS_TOOL_WIDTH:
63 case ABS_DISTANCE:
64 case ABS_TILT_X:
65 case ABS_TILT_Y:
66 case ABS_MT_SLOT:
67 case ABS_MT_TOUCH_MAJOR:
68 case ABS_MT_TOUCH_MINOR:
69 case ABS_MT_WIDTH_MAJOR:
70 case ABS_MT_WIDTH_MINOR:
71 case ABS_MT_ORIENTATION:
72 case ABS_MT_POSITION_X:
73 case ABS_MT_POSITION_Y:
74 case ABS_MT_TOOL_TYPE:
75 case ABS_MT_BLOB_ID:
76 case ABS_MT_TRACKING_ID:
77 case ABS_MT_PRESSURE:
78 case ABS_MT_DISTANCE:
79 return INPUT_DEVICE_CLASS_TOUCH;
80 }
81 }
82
83 // External stylus gets the pressure axis
84 if (deviceClasses & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
85 if (axis == ABS_PRESSURE) {
86 return INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
87 }
88 }
89
90 // Joystick devices get the rest.
91 return INPUT_DEVICE_CLASS_JOYSTICK;
92}
93
94static bool getBooleanProperty(const InputProperty& prop) {
95 const char* propValue = prop.getValue();
96 if (propValue == nullptr) return false;
97
98 char* end;
99 int value = std::strtol(propValue, &end, 10);
100 if (*end != '\0') {
101 ALOGW("Expected boolean for property %s; value=%s", prop.getKey(), propValue);
102 return false;
103 }
104 return value;
105}
106
107static void setDeviceClasses(const InputDeviceNode* node, uint32_t* classes) {
108 // See if this is a keyboard. Ignore everything in the button range except
109 // for joystick and gamepad buttons which are handled like keyboards for the
110 // most part.
111 bool haveKeyboardKeys = node->hasKeyInRange(0, BTN_MISC) ||
112 node->hasKeyInRange(KEY_OK, KEY_CNT);
113 bool haveGamepadButtons = node->hasKeyInRange(BTN_MISC, BTN_MOUSE) ||
114 node->hasKeyInRange(BTN_JOYSTICK, BTN_DIGI);
115 if (haveKeyboardKeys || haveGamepadButtons) {
116 *classes |= INPUT_DEVICE_CLASS_KEYBOARD;
117 }
118
119 // See if this is a cursor device such as a trackball or mouse.
120 if (node->hasKey(BTN_MOUSE)
121 && node->hasRelativeAxis(REL_X)
122 && node->hasRelativeAxis(REL_Y)) {
123 *classes |= INPUT_DEVICE_CLASS_CURSOR;
124 }
125
126 // See if this is a touch pad.
127 // Is this a new modern multi-touch driver?
128 if (node->hasAbsoluteAxis(ABS_MT_POSITION_X)
129 && node->hasAbsoluteAxis(ABS_MT_POSITION_Y)) {
130 // Some joysticks such as the PS3 controller report axes that conflict
131 // with the ABS_MT range. Try to confirm that the device really is a
132 // touch screen.
133 if (node->hasKey(BTN_TOUCH) || !haveGamepadButtons) {
134 *classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
135 }
136 // Is this an old style single-touch driver?
137 } else if (node->hasKey(BTN_TOUCH)
138 && node->hasAbsoluteAxis(ABS_X)
139 && node->hasAbsoluteAxis(ABS_Y)) {
140 *classes != INPUT_DEVICE_CLASS_TOUCH;
141 // Is this a BT stylus?
142 } else if ((node->hasAbsoluteAxis(ABS_PRESSURE) || node->hasKey(BTN_TOUCH))
143 && !node->hasAbsoluteAxis(ABS_X) && !node->hasAbsoluteAxis(ABS_Y)) {
144 *classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
145 // Keyboard will try to claim some of the buttons but we really want to
146 // reserve those so we can fuse it with the touch screen data, so just
147 // take them back. Note this means an external stylus cannot also be a
148 // keyboard device.
149 *classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
150 }
151
152 // See if this device is a joystick.
153 // Assumes that joysticks always have gamepad buttons in order to
154 // distinguish them from other devices such as accelerometers that also have
155 // absolute axes.
156 if (haveGamepadButtons) {
157 uint32_t assumedClasses = *classes | INPUT_DEVICE_CLASS_JOYSTICK;
158 for (int i = 0; i < ABS_CNT; ++i) {
159 if (node->hasAbsoluteAxis(i)
160 && getAbsAxisUsage(i, assumedClasses) == INPUT_DEVICE_CLASS_JOYSTICK) {
161 *classes = assumedClasses;
162 break;
163 }
164 }
165 }
166
167 // Check whether this device has switches.
168 for (int i = 0; i < SW_CNT; ++i) {
169 if (node->hasSwitch(i)) {
170 *classes |= INPUT_DEVICE_CLASS_SWITCH;
171 break;
172 }
173 }
174
175 // Check whether this device supports the vibrator.
176 if (node->hasForceFeedback(FF_RUMBLE)) {
177 *classes |= INPUT_DEVICE_CLASS_VIBRATOR;
178 }
179
180 // If the device isn't recognized as something we handle, don't monitor it.
181 // TODO
182
183 ALOGD("device %s classes=0x%x", node->getPath().c_str(), *classes);
184}
185
186EvdevDevice::EvdevDevice(InputHost host, const std::shared_ptr<InputDeviceNode>& node) :
187 mHost(host), mDeviceNode(node) {
188
189 InputBus bus = getInputBus(node);
190 mInputId = mHost.createDeviceIdentifier(
191 node->getName().c_str(),
192 node->getProductId(),
193 node->getVendorId(),
194 bus,
195 node->getUniqueId().c_str());
196
197 InputPropertyMap propMap = mHost.getDevicePropertyMap(mInputId);
198 setDeviceClasses(mDeviceNode.get(), &mClasses);
199}
Tim Kilbourn73475a42015-02-13 10:35:20 -0800200
201void EvdevDevice::processInput(InputEvent& event, nsecs_t currentTime) {
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700202#if DEBUG_INPUT_EVENTS
Tim Kilbourn73475a42015-02-13 10:35:20 -0800203 std::string log;
204 log.append("---InputEvent for device %s---\n");
205 log.append(" when: %" PRId64 "\n");
206 log.append(" type: %d\n");
207 log.append(" code: %d\n");
208 log.append(" value: %d\n");
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700209 ALOGD(log.c_str(), mDeviceNode->getPath().c_str(), event.when, event.type, event.code,
Tim Kilbourn73475a42015-02-13 10:35:20 -0800210 event.value);
Tim Kilbourn3186e7b2015-04-16 15:32:08 -0700211#endif
Tim Kilbourn73475a42015-02-13 10:35:20 -0800212
213 if (event.type == EV_MSC) {
214 if (event.code == MSC_ANDROID_TIME_SEC) {
215 mOverrideSec = event.value;
216 } else if (event.code == MSC_ANDROID_TIME_USEC) {
217 mOverrideUsec = event.value;
218 }
219 return;
220 }
221
222 if (mOverrideSec || mOverrideUsec) {
223 event.when = s2ns(mOverrideSec) + us2ns(mOverrideUsec);
224 ALOGV("applied override time %d.%06d", mOverrideSec, mOverrideUsec);
225
226 if (event.type == EV_SYN && event.code == SYN_REPORT) {
227 mOverrideSec = 0;
228 mOverrideUsec = 0;
229 }
230 }
231
232 // Bug 7291243: Add a guard in case the kernel generates timestamps
233 // that appear to be far into the future because they were generated
234 // using the wrong clock source.
235 //
236 // This can happen because when the input device is initially opened
237 // it has a default clock source of CLOCK_REALTIME. Any input events
238 // enqueued right after the device is opened will have timestamps
239 // generated using CLOCK_REALTIME. We later set the clock source
240 // to CLOCK_MONOTONIC but it is already too late.
241 //
242 // Invalid input event timestamps can result in ANRs, crashes and
243 // and other issues that are hard to track down. We must not let them
244 // propagate through the system.
245 //
246 // Log a warning so that we notice the problem and recover gracefully.
247 if (event.when >= currentTime + s2ns(10)) {
248 // Double-check. Time may have moved on.
249 auto time = systemTime(SYSTEM_TIME_MONOTONIC);
250 if (event.when > time) {
251 ALOGW("An input event from %s has a timestamp that appears to have "
252 "been generated using the wrong clock source (expected "
253 "CLOCK_MONOTONIC): event time %" PRId64 ", current time %" PRId64
254 ", call time %" PRId64 ". Using current time instead.",
255 mDeviceNode->getPath().c_str(), event.when, time, currentTime);
256 event.when = time;
257 } else {
258 ALOGV("Event time is ok but failed the fast path and required an extra "
259 "call to systemTime: event time %" PRId64 ", current time %" PRId64
260 ", call time %" PRId64 ".", event.when, time, currentTime);
261 }
262 }
263}
264
265} // namespace android