Home | History | Annotate | Download | only in input
      1 /*
      2  * Copyright (C) 2010 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 "VirtualKeyMap"
     18 
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 #include <input/VirtualKeyMap.h>
     23 #include <utils/Log.h>
     24 #include <utils/Errors.h>
     25 #include <utils/Tokenizer.h>
     26 #include <utils/Timers.h>
     27 
     28 // Enables debug output for the parser.
     29 #define DEBUG_PARSER 0
     30 
     31 namespace android {
     32 
     33 static const char* WHITESPACE = " \t\r";
     34 static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:";
     35 
     36 
     37 // --- VirtualKeyMap ---
     38 
     39 VirtualKeyMap::VirtualKeyMap() {
     40 }
     41 
     42 VirtualKeyMap::~VirtualKeyMap() {
     43 }
     44 
     45 std::unique_ptr<VirtualKeyMap> VirtualKeyMap::load(const std::string& filename) {
     46     Tokenizer* t;
     47     status_t status = Tokenizer::open(String8(filename.c_str()), &t);
     48     if (status != OK) {
     49         ALOGE("Error %d opening virtual key map file %s.", status, filename.c_str());
     50         return nullptr;
     51     }
     52     std::unique_ptr<Tokenizer> tokenizer(t);
     53     // Using 'new' to access a non-public constructor
     54     std::unique_ptr<VirtualKeyMap> map(new VirtualKeyMap());
     55     if (!map) {
     56         ALOGE("Error allocating virtual key map.");
     57         return nullptr;
     58     }
     59 
     60     Parser parser(map.get(), tokenizer.get());
     61     status = parser.parse();
     62     if (status != OK) {
     63         return nullptr;
     64     }
     65 
     66     return map;
     67 }
     68 
     69 
     70 // --- VirtualKeyMap::Parser ---
     71 
     72 VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) :
     73         mMap(map), mTokenizer(tokenizer) {
     74 }
     75 
     76 VirtualKeyMap::Parser::~Parser() {
     77 }
     78 
     79 status_t VirtualKeyMap::Parser::parse() {
     80     while (!mTokenizer->isEof()) {
     81 #if DEBUG_PARSER
     82         ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
     83                 mTokenizer->peekRemainderOfLine().string());
     84 #endif
     85 
     86         mTokenizer->skipDelimiters(WHITESPACE);
     87 
     88         if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
     89             // Multiple keys can appear on one line or they can be broken up across multiple lines.
     90             do {
     91                 String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
     92                 if (token != "0x01") {
     93                     ALOGE("%s: Unknown virtual key type, expected 0x01.",
     94                           mTokenizer->getLocation().string());
     95                     return BAD_VALUE;
     96                 }
     97 
     98                 VirtualKeyDefinition defn;
     99                 bool success = parseNextIntField(&defn.scanCode)
    100                         && parseNextIntField(&defn.centerX)
    101                         && parseNextIntField(&defn.centerY)
    102                         && parseNextIntField(&defn.width)
    103                         && parseNextIntField(&defn.height);
    104                 if (!success) {
    105                     ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.",
    106                           mTokenizer->getLocation().string());
    107                     return BAD_VALUE;
    108                 }
    109 
    110 #if DEBUG_PARSER
    111                 ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, "
    112                         "width=%d, height=%d",
    113                         defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height);
    114 #endif
    115                 mMap->mVirtualKeys.push_back(defn);
    116             } while (consumeFieldDelimiterAndSkipWhitespace());
    117 
    118             if (!mTokenizer->isEol()) {
    119                 ALOGE("%s: Expected end of line, got '%s'.",
    120                         mTokenizer->getLocation().string(),
    121                         mTokenizer->peekRemainderOfLine().string());
    122                 return BAD_VALUE;
    123             }
    124         }
    125 
    126         mTokenizer->nextLine();
    127     }
    128 
    129     return NO_ERROR;
    130 }
    131 
    132 bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() {
    133     mTokenizer->skipDelimiters(WHITESPACE);
    134     if (mTokenizer->peekChar() == ':') {
    135         mTokenizer->nextChar();
    136         mTokenizer->skipDelimiters(WHITESPACE);
    137         return true;
    138     }
    139     return false;
    140 }
    141 
    142 bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) {
    143     if (!consumeFieldDelimiterAndSkipWhitespace()) {
    144         return false;
    145     }
    146 
    147     String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
    148     char* end;
    149     *outValue = strtol(token.string(), &end, 0);
    150     if (token.isEmpty() || *end != '\0') {
    151         ALOGE("Expected an integer, got '%s'.", token.string());
    152         return false;
    153     }
    154     return true;
    155 }
    156 
    157 } // namespace android
    158