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#include <input/KeyCharacterMap.h>
18#include <input/KeyLayoutMap.h>
19#include <input/VirtualKeyMap.h>
20#include <utils/PropertyMap.h>
21#include <utils/String8.h>
22
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28using namespace android;
29
30static const char* kProgName = "validatekeymaps";
31static bool gQuiet = false;
32
33enum FileType {
34    FILETYPE_UNKNOWN,
35    FILETYPE_KEYLAYOUT,
36    FILETYPE_KEYCHARACTERMAP,
37    FILETYPE_VIRTUALKEYDEFINITION,
38    FILETYPE_INPUTDEVICECONFIGURATION,
39};
40
41static void log(const char* fmt, ...) {
42    if (gQuiet) {
43        return;
44    }
45    va_list args;
46    va_start(args, fmt);
47    vfprintf(stdout, fmt, args);
48    va_end(args);
49}
50
51static void error(const char* fmt,  ...) {
52    va_list args;
53    va_start(args, fmt);
54    vfprintf(stderr, fmt, args);
55    va_end(args);
56}
57
58static void usage() {
59    error("Keymap Validation Tool\n\n");
60    error("Usage:\n");
61    error(
62        " %s [-q] [*.kl] [*.kcm] [*.idc] [virtualkeys.*] [...]\n"
63        "   Validates the specified key layouts, key character maps, \n"
64        "   input device configurations, or virtual key definitions.\n\n"
65        "   -q Quiet; do not write anything to standard out.\n",
66        kProgName);
67}
68
69static FileType getFileType(const char* filename) {
70    const char *extension = strrchr(filename, '.');
71    if (extension) {
72        if (strcmp(extension, ".kl") == 0) {
73            return FILETYPE_KEYLAYOUT;
74        }
75        if (strcmp(extension, ".kcm") == 0) {
76            return FILETYPE_KEYCHARACTERMAP;
77        }
78        if (strcmp(extension, ".idc") == 0) {
79            return FILETYPE_INPUTDEVICECONFIGURATION;
80        }
81    }
82
83    if (strstr(filename, "virtualkeys.")) {
84        return FILETYPE_VIRTUALKEYDEFINITION;
85    }
86
87    return FILETYPE_UNKNOWN;
88}
89
90static bool validateFile(const char* filename) {
91    log("Validating file '%s'...\n", filename);
92
93    FileType fileType = getFileType(filename);
94    switch (fileType) {
95    case FILETYPE_UNKNOWN:
96        error("Supported file types: *.kl, *.kcm, virtualkeys.*\n\n");
97        return false;
98
99    case FILETYPE_KEYLAYOUT: {
100        sp<KeyLayoutMap> map;
101        status_t status = KeyLayoutMap::load(String8(filename), &map);
102        if (status) {
103            error("Error %d parsing key layout file.\n\n", status);
104            return false;
105        }
106        break;
107    }
108
109    case FILETYPE_KEYCHARACTERMAP: {
110        sp<KeyCharacterMap> map;
111        status_t status = KeyCharacterMap::load(String8(filename),
112                KeyCharacterMap::FORMAT_ANY, &map);
113        if (status) {
114            error("Error %d parsing key character map file.\n\n", status);
115            return false;
116        }
117        break;
118    }
119
120    case FILETYPE_INPUTDEVICECONFIGURATION: {
121        PropertyMap* map;
122        status_t status = PropertyMap::load(String8(filename), &map);
123        if (status) {
124            error("Error %d parsing input device configuration file.\n\n", status);
125            return false;
126        }
127        delete map;
128        break;
129    }
130
131    case FILETYPE_VIRTUALKEYDEFINITION: {
132        VirtualKeyMap* map;
133        status_t status = VirtualKeyMap::load(String8(filename), &map);
134        if (status) {
135            error("Error %d parsing virtual key definition file.\n\n", status);
136            return false;
137        }
138        delete map;
139        break;
140    }
141    }
142
143    log("No errors.\n\n");
144    return true;
145}
146
147int main(int argc, const char** argv) {
148    if (argc < 2) {
149        usage();
150        return 1;
151    }
152
153    int result = 0;
154    for (int i = 1; i < argc; i++) {
155        if (i == 1 && !strcmp(argv[1], "-q")) {
156            gQuiet = true;
157            continue;
158        }
159        if (!validateFile(argv[i])) {
160            result = 1;
161        }
162    }
163
164    if (result) {
165        error("Failed!\n");
166    } else {
167        log("Success.\n");
168    }
169    return result;
170}
171