2013-07-02 02:10:31 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define LOG_TAG "InputDevice"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include <input/InputDevice.h>
|
|
|
|
|
|
|
|
namespace android {
|
|
|
|
|
|
|
|
static const char* CONFIGURATION_FILE_DIR[] = {
|
|
|
|
"idc/",
|
|
|
|
"keylayout/",
|
|
|
|
"keychars/",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char* CONFIGURATION_FILE_EXTENSION[] = {
|
|
|
|
".idc",
|
|
|
|
".kl",
|
|
|
|
".kcm",
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool isValidNameChar(char ch) {
|
|
|
|
return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
|
|
|
|
}
|
|
|
|
|
|
|
|
static void appendInputDeviceConfigurationFileRelativePath(String8& path,
|
|
|
|
const String8& name, InputDeviceConfigurationFileType type) {
|
|
|
|
path.append(CONFIGURATION_FILE_DIR[type]);
|
|
|
|
for (size_t i = 0; i < name.length(); i++) {
|
|
|
|
char ch = name[i];
|
|
|
|
if (!isValidNameChar(ch)) {
|
|
|
|
ch = '_';
|
|
|
|
}
|
|
|
|
path.append(&ch, 1);
|
|
|
|
}
|
|
|
|
path.append(CONFIGURATION_FILE_EXTENSION[type]);
|
|
|
|
}
|
|
|
|
|
|
|
|
String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
|
|
|
|
const InputDeviceIdentifier& deviceIdentifier,
|
|
|
|
InputDeviceConfigurationFileType type) {
|
|
|
|
if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
|
|
|
|
if (deviceIdentifier.version != 0) {
|
|
|
|
// Try vendor product version.
|
|
|
|
String8 versionPath(getInputDeviceConfigurationFilePathByName(
|
|
|
|
String8::format("Vendor_%04x_Product_%04x_Version_%04x",
|
|
|
|
deviceIdentifier.vendor, deviceIdentifier.product,
|
|
|
|
deviceIdentifier.version),
|
|
|
|
type));
|
|
|
|
if (!versionPath.isEmpty()) {
|
|
|
|
return versionPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try vendor product.
|
|
|
|
String8 productPath(getInputDeviceConfigurationFilePathByName(
|
|
|
|
String8::format("Vendor_%04x_Product_%04x",
|
|
|
|
deviceIdentifier.vendor, deviceIdentifier.product),
|
|
|
|
type));
|
|
|
|
if (!productPath.isEmpty()) {
|
|
|
|
return productPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try device name.
|
|
|
|
return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
String8 getInputDeviceConfigurationFilePathByName(
|
|
|
|
const String8& name, InputDeviceConfigurationFileType type) {
|
|
|
|
// Search system repository.
|
|
|
|
String8 path;
|
|
|
|
path.setTo(getenv("ANDROID_ROOT"));
|
|
|
|
path.append("/usr/");
|
|
|
|
appendInputDeviceConfigurationFileRelativePath(path, name, type);
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
ALOGD("Probing for system provided input device configuration file: path='%s'", path.string());
|
|
|
|
#endif
|
|
|
|
if (!access(path.string(), R_OK)) {
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
ALOGD("Found");
|
|
|
|
#endif
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search user repository.
|
|
|
|
// TODO Should only look here if not in safe mode.
|
|
|
|
path.setTo(getenv("ANDROID_DATA"));
|
|
|
|
path.append("/system/devices/");
|
|
|
|
appendInputDeviceConfigurationFileRelativePath(path, name, type);
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
|
|
|
|
#endif
|
|
|
|
if (!access(path.string(), R_OK)) {
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
ALOGD("Found");
|
|
|
|
#endif
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not found.
|
|
|
|
#if DEBUG_PROBE
|
|
|
|
ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
|
|
|
|
name.string(), type);
|
|
|
|
#endif
|
|
|
|
return String8();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- InputDeviceInfo ---
|
|
|
|
|
|
|
|
InputDeviceInfo::InputDeviceInfo() {
|
2015-04-08 17:26:18 +00:00
|
|
|
initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false, false);
|
2013-07-02 02:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
|
2013-07-17 20:23:26 +00:00
|
|
|
mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber),
|
|
|
|
mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal),
|
2015-04-08 17:26:18 +00:00
|
|
|
mHasMic(other.mHasMic), mSources(other.mSources),
|
|
|
|
mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap),
|
|
|
|
mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad),
|
|
|
|
mMotionRanges(other.mMotionRanges) {
|
2013-07-02 02:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
InputDeviceInfo::~InputDeviceInfo() {
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:23:26 +00:00
|
|
|
void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
|
2015-04-08 17:26:18 +00:00
|
|
|
const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
|
|
|
|
bool hasMic) {
|
2013-07-02 02:10:31 +00:00
|
|
|
mId = id;
|
|
|
|
mGeneration = generation;
|
2013-07-17 20:23:26 +00:00
|
|
|
mControllerNumber = controllerNumber;
|
2013-07-02 02:10:31 +00:00
|
|
|
mIdentifier = identifier;
|
|
|
|
mAlias = alias;
|
|
|
|
mIsExternal = isExternal;
|
2015-04-08 17:26:18 +00:00
|
|
|
mHasMic = hasMic;
|
2013-07-02 02:10:31 +00:00
|
|
|
mSources = 0;
|
|
|
|
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
|
|
|
|
mHasVibrator = false;
|
2013-07-11 01:05:15 +00:00
|
|
|
mHasButtonUnderPad = false;
|
2013-07-02 02:10:31 +00:00
|
|
|
mMotionRanges.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
|
|
|
|
int32_t axis, uint32_t source) const {
|
|
|
|
size_t numRanges = mMotionRanges.size();
|
|
|
|
for (size_t i = 0; i < numRanges; i++) {
|
|
|
|
const MotionRange& range = mMotionRanges.itemAt(i);
|
|
|
|
if (range.axis == axis && range.source == source) {
|
|
|
|
return ⦥
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputDeviceInfo::addSource(uint32_t source) {
|
|
|
|
mSources |= source;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
|
|
|
|
float flat, float fuzz, float resolution) {
|
|
|
|
MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
|
|
|
|
mMotionRanges.add(range);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputDeviceInfo::addMotionRange(const MotionRange& range) {
|
|
|
|
mMotionRanges.add(range);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace android
|