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