15912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown/* 25912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown * Copyright (C) 2008 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 "KeyLayoutMap" 185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <stdlib.h> 205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <android/keycodes.h> 225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/Keyboard.h> 235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <input/KeyLayoutMap.h> 245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Log.h> 255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Errors.h> 265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Tokenizer.h> 275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#include <utils/Timers.h> 285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for the parser. 305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER 0 315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for parser performance. 335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_PARSER_PERFORMANCE 0 345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// Enables debug output for mapping. 365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#define DEBUG_MAPPING 0 375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownnamespace android { 405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatic const char* WHITESPACE = " \t\r"; 425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyLayoutMap --- 445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyLayoutMap::KeyLayoutMap() { 465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyLayoutMap::~KeyLayoutMap() { 495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) { 525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outMap->clear(); 535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Tokenizer* tokenizer; 555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = Tokenizer::open(filename, &tokenizer); 565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) { 575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error %d opening key layout map file %s.", status, filename.string()); 585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown sp<KeyLayoutMap> map = new KeyLayoutMap(); 605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!map.get()) { 615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("Error allocating key layout map."); 625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = NO_MEMORY; 635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); 665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Parser parser(map.get(), tokenizer); 685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status = parser.parse(); 695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER_PERFORMANCE 705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; 715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.", 725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown tokenizer->getFilename().string(), tokenizer->getLineNumber(), 735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown elapsedTime / 1000000.0); 745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!status) { 765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outMap = map; 775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown delete tokenizer; 805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return status; 825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, 855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t* outKeyCode, uint32_t* outFlags) const { 865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const Key* key = getKey(scanCode, usageCode); 875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!key) { 885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode); 905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKeyCode = AKEYCODE_UNKNOWN; 925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outFlags = 0; 935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NAME_NOT_FOUND; 945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outKeyCode = key->keyCode; 975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outFlags = key->flags; 985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 1005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.", 1015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown scanCode, usageCode, *outKeyCode, *outFlags); 1025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 1045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownconst KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { 1075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (usageCode) { 1085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); 1095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index >= 0) { 1105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return &mKeysByUsageCode.valueAt(index); 1115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (scanCode) { 1145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mKeysByScanCode.indexOfKey(scanCode); 1155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index >= 0) { 1165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return &mKeysByScanCode.valueAt(index); 1175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NULL; 1205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { 1235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown const size_t N = mKeysByScanCode.size(); 1245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (size_t i=0; i<N; i++) { 1255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mKeysByScanCode.valueAt(i).keyCode == keyCode) { 1265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outScanCodes->add(mKeysByScanCode.keyAt(i)); 1275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 1305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { 1335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ssize_t index = mAxes.indexOfKey(scanCode); 1345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (index < 0) { 1355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 1365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("mapAxis: scanCode=%d ~ Failed.", scanCode); 1375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NAME_NOT_FOUND; 1395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown *outAxisInfo = mAxes.valueAt(index); 1425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_MAPPING 1445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, " 1455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "splitValue=%d, flatOverride=%d.", 1465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown scanCode, 1475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis, 1485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown outAxisInfo->splitValue, outAxisInfo->flatOverride); 1495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 1515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown// --- KeyLayoutMap::Parser --- 1555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) : 1575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap(map), mTokenizer(tokenizer) { 1585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff BrownKeyLayoutMap::Parser::~Parser() { 1615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 1625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::Parser::parse() { 1645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown while (!mTokenizer->isEof()) { 1655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 1665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), 1675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 1685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 1695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 1735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keywordToken = mTokenizer->nextToken(WHITESPACE); 1745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (keywordToken == "key") { 1755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseKey(); 1775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 1785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (keywordToken == "axis") { 1795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown status_t status = parseAxis(); 1815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (status) return status; 1825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 1835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), 1845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keywordToken.string()); 1855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 1865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 1895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { 1905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected end of line or trailing comment, got '%s'.", 1915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), 1925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->peekRemainderOfLine().string()); 1935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 1945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 1975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->nextLine(); 1985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 1995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 2005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::Parser::parseKey() { 2035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 codeToken = mTokenizer->nextToken(WHITESPACE); 2045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown bool mapUsage = false; 2055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (codeToken == "usage") { 2065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage = true; 2075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 2085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown codeToken = mTokenizer->nextToken(WHITESPACE); 2095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char* end; 2125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); 2135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (*end) { 2145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(), 2155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", codeToken.string()); 2165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown KeyedVector<int32_t, Key>& map = 2195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; 2205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (map.indexOfKey(code) >= 0) { 2215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), 2225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", codeToken.string()); 2235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 2275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); 2285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); 2295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!keyCode) { 2305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), 2315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown keyCodeToken.string()); 2325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown uint32_t flags = 0; 2365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (;;) { 2375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 2385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break; 2395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 flagToken = mTokenizer->nextToken(WHITESPACE); 2415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown uint32_t flag = getKeyFlagByLabel(flagToken.string()); 2425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (!flag) { 2435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), 2445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown flagToken.string()); 2455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (flags & flag) { 2485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(), 2495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown flagToken.string()); 2505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown flags |= flag; 2535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 2565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.", 2575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mapUsage ? "usage" : "scan code", code, keyCode, flags); 2585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 2595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown Key key; 2605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key.keyCode = keyCode; 2615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown key.flags = flags; 2625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown map.add(code, key); 2635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 2645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 2655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brownstatus_t KeyLayoutMap::Parser::parseAxis() { 2675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); 2685912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown char* end; 2695912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); 2705912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (*end) { 2715912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(), 2725912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown scanCodeToken.string()); 2735912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2745912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2755912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mMap->mAxes.indexOfKey(scanCode) >= 0) { 2765912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(), 2775912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown scanCodeToken.string()); 2785912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2795912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2805912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2815912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown AxisInfo axisInfo; 2825912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2835912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 2845912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 token = mTokenizer->nextToken(WHITESPACE); 2855912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (token == "invert") { 2865912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.mode = AxisInfo::MODE_INVERT; 2875912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2885912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 2895912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 axisToken = mTokenizer->nextToken(WHITESPACE); 2905912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.axis = getAxisByLabel(axisToken.string()); 2915912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (axisInfo.axis < 0) { 2925912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected inverted axis label, got '%s'.", 2935912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), axisToken.string()); 2945912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 2955912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 2965912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else if (token == "split") { 2975912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.mode = AxisInfo::MODE_SPLIT; 2985912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 2995912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 3005912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 splitToken = mTokenizer->nextToken(WHITESPACE); 3015912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0)); 3025912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (*end) { 3035912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected split value, got '%s'.", 3045912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), splitToken.string()); 3055912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3065912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3075912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3085912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 3095912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); 3105912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.axis = getAxisByLabel(lowAxisToken.string()); 3115912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (axisInfo.axis < 0) { 3125912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected low axis label, got '%s'.", 3135912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), lowAxisToken.string()); 3145912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3155912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3165912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3175912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 3185912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); 3195912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); 3205912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (axisInfo.highAxis < 0) { 3215912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected high axis label, got '%s'.", 3225912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), highAxisToken.string()); 3235912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3245912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3255912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 3265912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.axis = getAxisByLabel(token.string()); 3275912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (axisInfo.axis < 0) { 3285912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", 3295912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), token.string()); 3305912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3315912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3325912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3335912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3345912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown for (;;) { 3355912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 3365912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') { 3375912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown break; 3385912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3395912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 keywordToken = mTokenizer->nextToken(WHITESPACE); 3405912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (keywordToken == "flat") { 3415912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->skipDelimiters(WHITESPACE); 3425912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown String8 flatToken = mTokenizer->nextToken(WHITESPACE); 3435912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0)); 3445912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown if (*end) { 3455912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected flat value, got '%s'.", 3465912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), flatToken.string()); 3475912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3485912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3495912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } else { 3505912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGE("%s: Expected keyword 'flat', got '%s'.", 3515912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mTokenizer->getLocation().string(), keywordToken.string()); 3525912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return BAD_VALUE; 3535912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3545912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown } 3555912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3565912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#if DEBUG_PARSER 3575912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown ALOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, " 3585912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown "splitValue=%d, flatOverride=%d.", 3595912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown scanCode, 3605912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.mode, axisInfo.axis, axisInfo.highAxis, 3615912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown axisInfo.splitValue, axisInfo.flatOverride); 3625912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown#endif 3635912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown mMap->mAxes.add(scanCode, axisInfo); 3645912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown return NO_ERROR; 3655912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown} 3665912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown 3675912f95d26f77d2b6df13e1f2672e48e3f9b871cJeff Brown}; 368