15912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown/* 25912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Copyright (C) 2012 The Android Open Source Project 35912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 45912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 55912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * you may not use this file except in compliance with the License. 65912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * You may obtain a copy of the License at 75912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 85912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 95912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * 105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Unless required by applicable law or agreed to in writing, software 115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * See the License for the specific language governing permissions and 145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * limitations under the License. 155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown */ 165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define LOG_TAG "InputDevice" 185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <stdlib.h> 205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <unistd.h> 215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <ctype.h> 225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/InputDevice.h> 247ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok#include <input/InputEventLabels.h> 255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownnamespace android { 275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* CONFIGURATION_FILE_DIR[] = { 295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "idc/", 305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "keylayout/", 315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "keychars/", 325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}; 335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* CONFIGURATION_FILE_EXTENSION[] = { 355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ".idc", 365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ".kl", 375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ".kcm", 385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}; 395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic bool isValidNameChar(char ch) { 415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); 425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic void appendInputDeviceConfigurationFileRelativePath(String8& path, 455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const String8& name, InputDeviceConfigurationFileType type) { 465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown path.append(CONFIGURATION_FILE_DIR[type]); 475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < name.length(); i++) { 485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char ch = name[i]; 495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!isValidNameChar(ch)) { 505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ch = '_'; 515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown path.append(&ch, 1); 535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown path.append(CONFIGURATION_FILE_EXTENSION[type]); 555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownString8 getInputDeviceConfigurationFilePathByDeviceIdentifier( 585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const InputDeviceIdentifier& deviceIdentifier, 595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown InputDeviceConfigurationFileType type) { 605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { 615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (deviceIdentifier.version != 0) { 625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Try vendor product version. 635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 versionPath(getInputDeviceConfigurationFilePathByName( 645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8::format("Vendor_%04x_Product_%04x_Version_%04x", 655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown deviceIdentifier.vendor, deviceIdentifier.product, 665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown deviceIdentifier.version), 675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type)); 685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!versionPath.isEmpty()) { 695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return versionPath; 705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Try vendor product. 745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 productPath(getInputDeviceConfigurationFilePathByName( 755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8::format("Vendor_%04x_Product_%04x", 765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown deviceIdentifier.vendor, deviceIdentifier.product), 775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown type)); 785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!productPath.isEmpty()) { 795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return productPath; 805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Try device name. 845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); 855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownString8 getInputDeviceConfigurationFilePathByName( 885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const String8& name, InputDeviceConfigurationFileType type) { 895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Search system repository. 905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 path; 917ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok 927ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok // Treblized input device config files will be located /odm/usr or /vendor/usr. 939e94788e8a8388eeb1113dc42c932ed42008de5dFrank Barchard const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")}; 947ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok for (size_t i = 0; i < size(rootsForPartition); i++) { 957ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok path.setTo(rootsForPartition[i]); 967ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok path.append("/usr/"); 977ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok appendInputDeviceConfigurationFileRelativePath(path, name, type); 985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PROBE 997ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok ALOGD("Probing for system provided input device configuration file: path='%s'", 1007ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok path.string()); 1015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1027ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok if (!access(path.string(), R_OK)) { 1035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PROBE 1047ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok ALOGD("Found"); 1055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1067ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok return path; 1077ead73ed26403405bddd625c6ea0f009bff92939Jaekyun Seok } 1085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Search user repository. 1115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // TODO Should only look here if not in safe mode. 1125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown path.setTo(getenv("ANDROID_DATA")); 1135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown path.append("/system/devices/"); 1145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown appendInputDeviceConfigurationFileRelativePath(path, name, type); 1155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PROBE 1165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Probing for system user input device configuration file: path='%s'", path.string()); 1175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!access(path.string(), R_OK)) { 1195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PROBE 1205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Found"); 1215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return path; 1235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown // Not found. 1265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PROBE 1275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Probe failed to find input device configuration file: name='%s', type=%d", 1285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown name.string(), type); 1295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return String8(); 1315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- InputDeviceInfo --- 1355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownInputDeviceInfo::InputDeviceInfo() { 137063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false, false); 1385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownInputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : 1410415d63b1adf15f6546fea902c66f8bd508afbfcMichael Wright mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber), 1420415d63b1adf15f6546fea902c66f8bd508afbfcMichael Wright mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal), 143063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn mHasMic(other.mHasMic), mSources(other.mSources), 144063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap), 145063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad), 146063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn mMotionRanges(other.mMotionRanges) { 1475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownInputDeviceInfo::~InputDeviceInfo() { 1505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1520415d63b1adf15f6546fea902c66f8bd508afbfcMichael Wrightvoid InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber, 153063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal, 154063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn bool hasMic) { 1555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mId = id; 1565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mGeneration = generation; 1570415d63b1adf15f6546fea902c66f8bd508afbfcMichael Wright mControllerNumber = controllerNumber; 1585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mIdentifier = identifier; 1595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mAlias = alias; 1605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mIsExternal = isExternal; 161063ff53d0b0a0d670ea0185e687526d8fd302820Tim Kilbourn mHasMic = hasMic; 1625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mSources = 0; 1635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; 1645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mHasVibrator = false; 165931fd6dee7891e94650353c09956ccf24b4dfff3Michael Wright mHasButtonUnderPad = false; 1665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMotionRanges.clear(); 1675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownconst InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( 1705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t axis, uint32_t source) const { 1715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown size_t numRanges = mMotionRanges.size(); 1725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i = 0; i < numRanges; i++) { 1735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const MotionRange& range = mMotionRanges.itemAt(i); 1745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (range.axis == axis && range.source == source) { 1755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return ⦥ 1765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 1795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid InputDeviceInfo::addSource(uint32_t source) { 1825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mSources |= source; 1835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, 1865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown float flat, float fuzz, float resolution) { 1875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown MotionRange range = { axis, source, min, max, flat, fuzz, resolution }; 1885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMotionRanges.add(range); 1895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownvoid InputDeviceInfo::addMotionRange(const MotionRange& range) { 1925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMotionRanges.add(range); 1935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} // namespace android 196