|
1 /* |
|
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 "InputDevice.h" |
|
24 |
|
25 namespace android { |
|
26 |
|
27 static const char* CONFIGURATION_FILE_DIR[] = { |
|
28 "idc/", |
|
29 "keylayout/", |
|
30 "keychars/", |
|
31 }; |
|
32 |
|
33 static const char* CONFIGURATION_FILE_EXTENSION[] = { |
|
34 ".idc", |
|
35 ".kl", |
|
36 ".kcm", |
|
37 }; |
|
38 |
|
39 static bool isValidNameChar(char ch) { |
|
40 return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); |
|
41 } |
|
42 |
|
43 static 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 |
|
56 String8 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 |
|
86 String8 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 |
|
129 InputDeviceInfo::InputDeviceInfo() { |
|
130 initialize(-1, -1, InputDeviceIdentifier(), String8(), false); |
|
131 } |
|
132 |
|
133 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : |
|
134 mId(other.mId), mGeneration(other.mGeneration), mIdentifier(other.mIdentifier), |
|
135 mAlias(other.mAlias), mIsExternal(other.mIsExternal), mSources(other.mSources), |
|
136 mKeyboardType(other.mKeyboardType), |
|
137 mKeyCharacterMap(other.mKeyCharacterMap), |
|
138 mHasVibrator(other.mHasVibrator), |
|
139 mMotionRanges(other.mMotionRanges) { |
|
140 } |
|
141 |
|
142 InputDeviceInfo::~InputDeviceInfo() { |
|
143 } |
|
144 |
|
145 void InputDeviceInfo::initialize(int32_t id, int32_t generation, |
|
146 const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal) { |
|
147 mId = id; |
|
148 mGeneration = generation; |
|
149 mIdentifier = identifier; |
|
150 mAlias = alias; |
|
151 mIsExternal = isExternal; |
|
152 mSources = 0; |
|
153 mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; |
|
154 mHasVibrator = false; |
|
155 mMotionRanges.clear(); |
|
156 } |
|
157 |
|
158 const 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 ⦥ |
|
165 } |
|
166 } |
|
167 return NULL; |
|
168 } |
|
169 |
|
170 void InputDeviceInfo::addSource(uint32_t source) { |
|
171 mSources |= source; |
|
172 } |
|
173 |
|
174 void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, |
|
175 float flat, float fuzz, float resolution) { |
|
176 MotionRange range = { axis, source, min, max, flat, fuzz, resolution }; |
|
177 mMotionRanges.add(range); |
|
178 } |
|
179 |
|
180 void InputDeviceInfo::addMotionRange(const MotionRange& range) { |
|
181 mMotionRanges.add(range); |
|
182 } |
|
183 |
|
184 } // namespace android |