Home | History | Annotate | Download | only in input
      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 <android-base/stringprintf.h>
     24 #include <input/InputDevice.h>
     25 #include <input/InputEventLabels.h>
     26 
     27 using android::base::StringPrintf;
     28 
     29 namespace android {
     30 
     31 static const char* CONFIGURATION_FILE_DIR[] = {
     32         "idc/",
     33         "keylayout/",
     34         "keychars/",
     35 };
     36 
     37 static const char* CONFIGURATION_FILE_EXTENSION[] = {
     38         ".idc",
     39         ".kl",
     40         ".kcm",
     41 };
     42 
     43 static bool isValidNameChar(char ch) {
     44     return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
     45 }
     46 
     47 static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
     48         const std::string& name, InputDeviceConfigurationFileType type) {
     49     path += CONFIGURATION_FILE_DIR[type];
     50     path += name;
     51     path += CONFIGURATION_FILE_EXTENSION[type];
     52 }
     53 
     54 std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
     55         const InputDeviceIdentifier& deviceIdentifier,
     56         InputDeviceConfigurationFileType type) {
     57     if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
     58         if (deviceIdentifier.version != 0) {
     59             // Try vendor product version.
     60             std::string versionPath = getInputDeviceConfigurationFilePathByName(
     61                     StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
     62                             deviceIdentifier.vendor, deviceIdentifier.product,
     63                             deviceIdentifier.version),
     64                     type);
     65             if (!versionPath.empty()) {
     66                 return versionPath;
     67             }
     68         }
     69 
     70         // Try vendor product.
     71         std::string productPath = getInputDeviceConfigurationFilePathByName(
     72                 StringPrintf("Vendor_%04x_Product_%04x",
     73                         deviceIdentifier.vendor, deviceIdentifier.product),
     74                 type);
     75         if (!productPath.empty()) {
     76             return productPath;
     77         }
     78     }
     79 
     80     // Try device name.
     81     return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type);
     82 }
     83 
     84 std::string getInputDeviceConfigurationFilePathByName(
     85         const std::string& name, InputDeviceConfigurationFileType type) {
     86     // Search system repository.
     87     std::string path;
     88 
     89     // Treblized input device config files will be located /odm/usr or /vendor/usr.
     90     const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
     91     for (size_t i = 0; i < size(rootsForPartition); i++) {
     92         if (rootsForPartition[i] == nullptr) {
     93             continue;
     94         }
     95         path = rootsForPartition[i];
     96         path += "/usr/";
     97         appendInputDeviceConfigurationFileRelativePath(path, name, type);
     98 #if DEBUG_PROBE
     99         ALOGD("Probing for system provided input device configuration file: path='%s'",
    100               path.c_str());
    101 #endif
    102         if (!access(path.c_str(), R_OK)) {
    103 #if DEBUG_PROBE
    104             ALOGD("Found");
    105 #endif
    106             return path;
    107         }
    108     }
    109 
    110     // Search user repository.
    111     // TODO Should only look here if not in safe mode.
    112     path = "";
    113     char *androidData = getenv("ANDROID_DATA");
    114     if (androidData != nullptr) {
    115         path += androidData;
    116     }
    117     path += "/system/devices/";
    118     appendInputDeviceConfigurationFileRelativePath(path, name, type);
    119 #if DEBUG_PROBE
    120     ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
    121 #endif
    122     if (!access(path.c_str(), R_OK)) {
    123 #if DEBUG_PROBE
    124         ALOGD("Found");
    125 #endif
    126         return path;
    127     }
    128 
    129     // Not found.
    130 #if DEBUG_PROBE
    131     ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
    132             name.c_str(), type);
    133 #endif
    134     return "";
    135 }
    136 
    137 // --- InputDeviceIdentifier
    138 
    139 std::string InputDeviceIdentifier::getCanonicalName() const {
    140     std::string replacedName = name;
    141     for (char& ch : replacedName) {
    142         if (!isValidNameChar(ch)) {
    143             ch = '_';
    144         }
    145     }
    146     return replacedName;
    147 }
    148 
    149 
    150 // --- InputDeviceInfo ---
    151 
    152 InputDeviceInfo::InputDeviceInfo() {
    153     initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false);
    154 }
    155 
    156 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
    157         mId(other.mId), mGeneration(other.mGeneration), mControllerNumber(other.mControllerNumber),
    158         mIdentifier(other.mIdentifier), mAlias(other.mAlias), mIsExternal(other.mIsExternal),
    159         mHasMic(other.mHasMic), mSources(other.mSources),
    160         mKeyboardType(other.mKeyboardType), mKeyCharacterMap(other.mKeyCharacterMap),
    161         mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad),
    162         mMotionRanges(other.mMotionRanges) {
    163 }
    164 
    165 InputDeviceInfo::~InputDeviceInfo() {
    166 }
    167 
    168 void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
    169         const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
    170         bool hasMic) {
    171     mId = id;
    172     mGeneration = generation;
    173     mControllerNumber = controllerNumber;
    174     mIdentifier = identifier;
    175     mAlias = alias;
    176     mIsExternal = isExternal;
    177     mHasMic = hasMic;
    178     mSources = 0;
    179     mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
    180     mHasVibrator = false;
    181     mHasButtonUnderPad = false;
    182     mMotionRanges.clear();
    183 }
    184 
    185 const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
    186         int32_t axis, uint32_t source) const {
    187     size_t numRanges = mMotionRanges.size();
    188     for (size_t i = 0; i < numRanges; i++) {
    189         const MotionRange& range = mMotionRanges[i];
    190         if (range.axis == axis && range.source == source) {
    191             return &range;
    192         }
    193     }
    194     return nullptr;
    195 }
    196 
    197 void InputDeviceInfo::addSource(uint32_t source) {
    198     mSources |= source;
    199 }
    200 
    201 void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
    202         float flat, float fuzz, float resolution) {
    203     MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
    204     mMotionRanges.push_back(range);
    205 }
    206 
    207 void InputDeviceInfo::addMotionRange(const MotionRange& range) {
    208     mMotionRanges.push_back(range);
    209 }
    210 
    211 } // namespace android
    212