blob: f7420523f176d7063fe05150cc11b17e071c51a9 [file] [log] [blame]
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001/*
2 * Copyright (C) 2012 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
19#include <stdlib.h>
20#include <unistd.h>
21#include <ctype.h>
22
23#include <androidfw/InputDevice.h>
24
25namespace android {
26
27static const char* CONFIGURATION_FILE_DIR[] = {
28 "idc/",
29 "keylayout/",
30 "keychars/",
31};
32
33static const char* CONFIGURATION_FILE_EXTENSION[] = {
34 ".idc",
35 ".kl",
36 ".kcm",
37};
38
39static bool isValidNameChar(char ch) {
40 return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
41}
42
43static void appendInputDeviceConfigurationFileRelativePath(String8& path,
44 const String8& name, InputDeviceConfigurationFileType type) {
45 path.append(CONFIGURATION_FILE_DIR[type]);
46 for (size_t i = 0; i < name.length(); i++) {
47 char ch = name[i];
48 if (!isValidNameChar(ch)) {
49 ch = '_';
50 }
51 path.append(&ch, 1);
52 }
53 path.append(CONFIGURATION_FILE_EXTENSION[type]);
54}
55
56String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
57 const InputDeviceIdentifier& deviceIdentifier,
58 InputDeviceConfigurationFileType type) {
59 if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
60 if (deviceIdentifier.version != 0) {
61 // Try vendor product version.
62 String8 versionPath(getInputDeviceConfigurationFilePathByName(
63 String8::format("Vendor_%04x_Product_%04x_Version_%04x",
64 deviceIdentifier.vendor, deviceIdentifier.product,
65 deviceIdentifier.version),
66 type));
67 if (!versionPath.isEmpty()) {
68 return versionPath;
69 }
70 }
71
72 // Try vendor product.
73 String8 productPath(getInputDeviceConfigurationFilePathByName(
74 String8::format("Vendor_%04x_Product_%04x",
75 deviceIdentifier.vendor, deviceIdentifier.product),
76 type));
77 if (!productPath.isEmpty()) {
78 return productPath;
79 }
80 }
81
82 // Try device name.
83 return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
84}
85
86String8 getInputDeviceConfigurationFilePathByName(
87 const String8& name, InputDeviceConfigurationFileType type) {
88 // Search system repository.
89 String8 path;
90 path.setTo(getenv("ANDROID_ROOT"));
91 path.append("/usr/");
92 appendInputDeviceConfigurationFileRelativePath(path, name, type);
93#if DEBUG_PROBE
94 ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());
95#endif
96 if (!access(path.string(), R_OK)) {
97#if DEBUG_PROBE
98 ALOGD("Found");
99#endif
100 return path;
101 }
102
103 // Search user repository.
104 // TODO Should only look here if not in safe mode.
105 path.setTo(getenv("ANDROID_DATA"));
106 path.append("/system/devices/");
107 appendInputDeviceConfigurationFileRelativePath(path, name, type);
108#if DEBUG_PROBE
109 ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
110#endif
111 if (!access(path.string(), R_OK)) {
112#if DEBUG_PROBE
113 ALOGD("Found");
114#endif
115 return path;
116 }
117
118 // Not found.
119#if DEBUG_PROBE
120 ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
121 name.string(), type);
122#endif
123 return String8();
124}
125
126
127// --- InputDeviceInfo ---
128
129InputDeviceInfo::InputDeviceInfo() {
Jeff Browndaa37532012-05-01 15:54:03 -0700130 initialize(-1, -1, InputDeviceIdentifier(), String8(), false);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700131}
132
133InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700134 mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier),
Jeff Browndaa37532012-05-01 15:54:03 -0700135 mAlias(other.mAlias), mIsExternal(other.mIsExternal), mSources(other.mSources),
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700136 mKeyboardType(other.mKeyboardType),
137 mKeyCharacterMap(other.mKeyCharacterMap),
Jeff Browna47425a2012-04-13 04:09:27 -0700138 mHasVibrator(other.mHasVibrator),
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700139 mMotionRanges(other.mMotionRanges) {
140}
141
142InputDeviceInfo::~InputDeviceInfo() {
143}
144
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700145void InputDeviceInfo::initialize(int32_t id, int32_t generation,
Jeff Browndaa37532012-05-01 15:54:03 -0700146 const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700147 mId = id;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700148 mGeneration = generation;
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700149 mIdentifier = identifier;
150 mAlias = alias;
Jeff Browndaa37532012-05-01 15:54:03 -0700151 mIsExternal = isExternal;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700152 mSources = 0;
153 mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
Jeff Browna47425a2012-04-13 04:09:27 -0700154 mHasVibrator = false;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700155 mMotionRanges.clear();
156}
157
158const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
159 int32_t axis, uint32_t source) const {
160 size_t numRanges = mMotionRanges.size();
161 for (size_t i = 0; i < numRanges; i++) {
162 const MotionRange& range = mMotionRanges.itemAt(i);
163 if (range.axis == axis && range.source == source) {
164 return &range;
165 }
166 }
167 return NULL;
168}
169
170void InputDeviceInfo::addSource(uint32_t source) {
171 mSources |= source;
172}
173
174void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
Michael Wrightc6091c62013-04-01 20:56:04 -0700175 float flat, float fuzz, float resolution) {
176 MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700177 mMotionRanges.add(range);
178}
179
180void InputDeviceInfo::addMotionRange(const MotionRange& range) {
181 mMotionRanges.add(range);
182}
183
184} // namespace android