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 
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* kProgName = "validatekeymaps";
30 static bool gQuiet = false;
31 
32 enum FileType {
33     FILETYPE_UNKNOWN,
34     FILETYPE_KEYLAYOUT,
35     FILETYPE_KEYCHARACTERMAP,
36     FILETYPE_VIRTUALKEYDEFINITION,
37     FILETYPE_INPUTDEVICECONFIGURATION,
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(
61         " %s [-q] [*.kl] [*.kcm] [*.idc] [virtualkeys.*] [...]\n"
62         "   Validates the specified key layouts, key character maps, \n"
63         "   input device configurations, or virtual key definitions.\n\n"
64         "   -q Quiet; do not write anything to standard out.\n",
65         kProgName);
66 }
67 
getFileType(const char * filename)68 static FileType getFileType(const char* filename) {
69     const char *extension = strrchr(filename, '.');
70     if (extension) {
71         if (strcmp(extension, ".kl") == 0) {
72             return FILETYPE_KEYLAYOUT;
73         }
74         if (strcmp(extension, ".kcm") == 0) {
75             return FILETYPE_KEYCHARACTERMAP;
76         }
77         if (strcmp(extension, ".idc") == 0) {
78             return FILETYPE_INPUTDEVICECONFIGURATION;
79         }
80     }
81 
82     if (strstr(filename, "virtualkeys.")) {
83         return FILETYPE_VIRTUALKEYDEFINITION;
84     }
85 
86     return FILETYPE_UNKNOWN;
87 }
88 
validateFile(const char * filename)89 static bool validateFile(const char* filename) {
90     log("Validating file '%s'...\n", filename);
91 
92     FileType fileType = getFileType(filename);
93     switch (fileType) {
94     case FILETYPE_UNKNOWN:
95         error("Supported file types: *.kl, *.kcm, virtualkeys.*\n\n");
96         return false;
97 
98     case FILETYPE_KEYLAYOUT: {
99         sp<KeyLayoutMap> map;
100         status_t status = KeyLayoutMap::load(filename, &map);
101         if (status) {
102             error("Error %d parsing key layout file.\n\n", status);
103             return false;
104         }
105         break;
106     }
107 
108     case FILETYPE_KEYCHARACTERMAP: {
109         sp<KeyCharacterMap> map;
110         status_t status = KeyCharacterMap::load(filename,
111                 KeyCharacterMap::FORMAT_ANY, &map);
112         if (status) {
113             error("Error %d parsing key character map file.\n\n", status);
114             return false;
115         }
116         break;
117     }
118 
119     case FILETYPE_INPUTDEVICECONFIGURATION: {
120         PropertyMap* map;
121         status_t status = PropertyMap::load(String8(filename), &map);
122         if (status) {
123             error("Error %d parsing input device configuration file.\n\n", status);
124             return false;
125         }
126         delete map;
127         break;
128     }
129 
130     case FILETYPE_VIRTUALKEYDEFINITION: {
131         std::unique_ptr<VirtualKeyMap> map = VirtualKeyMap::load(filename);
132         if (!map) {
133             error("Error while parsing virtual key definition file.\n\n");
134             return false;
135         }
136         break;
137     }
138     }
139 
140     log("No errors.\n\n");
141     return true;
142 }
143 
main(int argc,const char ** argv)144 int main(int argc, const char** argv) {
145     if (argc < 2) {
146         usage();
147         return 1;
148     }
149 
150     int result = 0;
151     for (int i = 1; i < argc; i++) {
152         if (i == 1 && !strcmp(argv[1], "-q")) {
153             gQuiet = true;
154             continue;
155         }
156         if (!validateFile(argv[i])) {
157             result = 1;
158         }
159     }
160 
161     if (result) {
162         error("Failed!\n");
163     } else {
164         log("Success.\n");
165     }
166     return result;
167 }
168