1#define LOG_TAG "KeyLayoutMap" 2 3#include "KeyLayoutMap.h" 4#include <sys/types.h> 5#include <sys/stat.h> 6#include <fcntl.h> 7#include <unistd.h> 8#include <errno.h> 9#include <utils/String8.h> 10#include <stdlib.h> 11#include <ui/KeycodeLabels.h> 12#include <utils/Log.h> 13 14namespace android { 15 16KeyLayoutMap::KeyLayoutMap() 17 :m_status(NO_INIT), 18 m_keys() 19{ 20} 21 22KeyLayoutMap::~KeyLayoutMap() 23{ 24} 25 26static String8 27next_token(char const** p, int *line) 28{ 29 bool begun = false; 30 const char* begin = *p; 31 const char* end = *p; 32 while (true) { 33 if (*end == '\n') { 34 (*line)++; 35 } 36 switch (*end) 37 { 38 case '#': 39 if (begun) { 40 *p = end; 41 return String8(begin, end-begin); 42 } else { 43 do { 44 begin++; 45 end++; 46 } while (*begin != '\0' && *begin != '\n'); 47 } 48 case '\0': 49 case ' ': 50 case '\n': 51 case '\r': 52 case '\t': 53 if (begun || (*end == '\0')) { 54 *p = end; 55 return String8(begin, end-begin); 56 } else { 57 begin++; 58 end++; 59 break; 60 } 61 default: 62 end++; 63 begun = true; 64 } 65 } 66} 67 68static int32_t 69token_to_value(const char *literal, const KeycodeLabel *list) 70{ 71 while (list->literal) { 72 if (0 == strcmp(literal, list->literal)) { 73 return list->value; 74 } 75 list++; 76 } 77 return list->value; 78} 79 80status_t 81KeyLayoutMap::load(const char* filename) 82{ 83 int fd = open(filename, O_RDONLY); 84 if (fd < 0) { 85 LOGE("error opening file=%s err=%s\n", filename, strerror(errno)); 86 m_status = errno; 87 return errno; 88 } 89 90 off_t len = lseek(fd, 0, SEEK_END); 91 off_t errlen = lseek(fd, 0, SEEK_SET); 92 if (len < 0 || errlen < 0) { 93 close(fd); 94 LOGE("error seeking file=%s err=%s\n", filename, strerror(errno)); 95 m_status = errno; 96 return errno; 97 } 98 99 char* buf = (char*)malloc(len+1); 100 if (read(fd, buf, len) != len) { 101 LOGE("error reading file=%s err=%s\n", filename, strerror(errno)); 102 m_status = errno != 0 ? errno : ((int)NOT_ENOUGH_DATA); 103 return errno != 0 ? errno : ((int)NOT_ENOUGH_DATA); 104 } 105 errno = 0; 106 buf[len] = '\0'; 107 108 int32_t scancode = -1; 109 int32_t keycode = -1; 110 uint32_t flags = 0; 111 uint32_t tmp; 112 char* end; 113 status_t err = NO_ERROR; 114 int line = 1; 115 char const* p = buf; 116 enum { BEGIN, SCANCODE, KEYCODE, FLAG } state = BEGIN; 117 while (true) { 118 String8 token = next_token(&p, &line); 119 if (*p == '\0') { 120 break; 121 } 122 switch (state) 123 { 124 case BEGIN: 125 if (token == "key") { 126 state = SCANCODE; 127 } else { 128 LOGE("%s:%d: expected key, got '%s'\n", filename, line, 129 token.string()); 130 err = BAD_VALUE; 131 goto done; 132 } 133 break; 134 case SCANCODE: 135 scancode = strtol(token.string(), &end, 0); 136 if (*end != '\0') { 137 LOGE("%s:%d: expected scancode (a number), got '%s'\n", 138 filename, line, token.string()); 139 goto done; 140 } 141 //LOGI("%s:%d: got scancode %d\n", filename, line, scancode ); 142 state = KEYCODE; 143 break; 144 case KEYCODE: 145 keycode = token_to_value(token.string(), KEYCODES); 146 //LOGI("%s:%d: got keycode %d for %s\n", filename, line, keycode, token.string() ); 147 if (keycode == 0) { 148 LOGE("%s:%d: expected keycode, got '%s'\n", 149 filename, line, token.string()); 150 goto done; 151 } 152 state = FLAG; 153 break; 154 case FLAG: 155 if (token == "key") { 156 if (scancode != -1) { 157 //LOGI("got key decl scancode=%d keycode=%d" 158 // " flags=0x%08x\n", scancode, keycode, flags); 159 Key k = { keycode, flags }; 160 m_keys.add(scancode, k); 161 state = SCANCODE; 162 scancode = -1; 163 keycode = -1; 164 flags = 0; 165 break; 166 } 167 } 168 tmp = token_to_value(token.string(), FLAGS); 169 //LOGI("%s:%d: got flags %x for %s\n", filename, line, tmp, token.string() ); 170 if (tmp == 0) { 171 LOGE("%s:%d: expected flag, got '%s'\n", 172 filename, line, token.string()); 173 goto done; 174 } 175 flags |= tmp; 176 break; 177 } 178 } 179 if (state == FLAG && scancode != -1 ) { 180 //LOGI("got key decl scancode=%d keycode=%d" 181 // " flags=0x%08x\n", scancode, keycode, flags); 182 Key k = { keycode, flags }; 183 m_keys.add(scancode, k); 184 } 185 186done: 187 free(buf); 188 close(fd); 189 190 m_status = err; 191 return err; 192} 193 194status_t 195KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags) const 196{ 197 if (m_status != NO_ERROR) { 198 return m_status; 199 } 200 201 ssize_t index = m_keys.indexOfKey(scancode); 202 if (index < 0) { 203 //LOGW("couldn't map scancode=%d\n", scancode); 204 return NAME_NOT_FOUND; 205 } 206 207 const Key& k = m_keys.valueAt(index); 208 209 *keycode = k.keycode; 210 *flags = k.flags; 211 212 //LOGD("mapped scancode=%d to keycode=%d flags=0x%08x\n", scancode, 213 // keycode, flags); 214 215 return NO_ERROR; 216} 217 218status_t 219KeyLayoutMap::findScancodes(int32_t keycode, Vector<int32_t>* outScancodes) const 220{ 221 if (m_status != NO_ERROR) { 222 return m_status; 223 } 224 225 const size_t N = m_keys.size(); 226 for (size_t i=0; i<N; i++) { 227 if (m_keys.valueAt(i).keycode == keycode) { 228 outScancodes->add(m_keys.keyAt(i)); 229 } 230 } 231 232 return NO_ERROR; 233} 234 235}; 236