19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "KeyCharacterMap" 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/KeyCharacterMap.h> 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/properties.h> 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <limits.h> 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct Header 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char magic[8]; 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int endian; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int version; 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int keycount; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned char kbdtype; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char padding[11]; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::KeyCharacterMap() 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::~KeyCharacterMap() 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(m_keys); 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned short 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::get(int keycode, int meta) 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* k = find_key(keycode); 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (k != NULL) { 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return k->data[meta & META_MASK]; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned short 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::getNumber(int keycode) 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* k = find_key(keycode); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (k != NULL) { 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return k->number; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned short 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::getMatch(int keycode, const unsigned short* chars, 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int charsize, uint32_t modifiers) 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* k = find_key(keycode); 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project modifiers &= 3; // ignore the SYM key because we don't have keymap entries for it 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (k != NULL) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const uint16_t* data = k->data; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<charsize; j++) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint16_t c = chars[j]; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<(META_MASK + 1); i++) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((modifiers == 0) || ((modifiers & i) != 0)) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == data[i]) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return c; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned short 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::getDisplayLabel(int keycode) 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* k = find_key(keycode); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (k != NULL) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return k->display_label; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::getKeyData(int keycode, unsigned short *displayLabel, 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned short *number, unsigned short* results) 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* k = find_key(keycode); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (k != NULL) { 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(results, k->data, sizeof(short)*(META_MASK + 1)); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *number = k->number; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *displayLabel = k->display_label; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::find_char(uint16_t c, uint32_t* key, uint32_t* mods) 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t N = m_keyCount; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=0; j<(META_MASK + 1); j++) { 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key const* keys = m_keys; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (uint32_t i=0; i<N; i++) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keys->data[j] == c) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *key = keys->keycode; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *mods = j; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keys++; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::getEvents(uint16_t* chars, size_t len, 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Vector<int32_t>* keys, Vector<uint32_t>* modifiers) 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i=0; i<len; i++) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t k, mods; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (find_char(chars[i], &k, &mods)) { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keys->add(k); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project modifiers->add(mods); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::Key* 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::find_key(int keycode) 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* keys = m_keys; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int low = 0; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int high = m_keyCount - 1; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mid; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (low <= high) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mid = (low + high) / 2; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n = keys[mid].keycode; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (keycode < n) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project high = mid - 1; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (keycode > n) { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project low = mid + 1; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return keys + mid; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap* 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::load(int id) 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyCharacterMap* rv = NULL; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char path[PATH_MAX]; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char propName[100]; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char dev[PROPERTY_VALUE_MAX]; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char tmpfn[PROPERTY_VALUE_MAX]; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* root = getenv("ANDROID_ROOT"); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sprintf(propName, "hw.keyboards.%u.devname", id); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = property_get(propName, dev, ""); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err > 0) { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // replace all the spaces with underscores 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcpy(tmpfn, dev); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' ')) 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *p = '_'; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, tmpfn); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGD("load: dev='%s' path='%s'\n", dev, path); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv = try_file(path); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rv != NULL) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rv; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, dev); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("No keyboard for id %d", id); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(path, sizeof(path), "%s/usr/keychars/qwerty.kcm.bin", root); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv = try_file(path); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rv == NULL) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find any keycharmaps (also tried %s)", path); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Using default keymap: %s", path); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rv; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap* 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectKeyCharacterMap::try_file(const char* filename) 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project KeyCharacterMap* rv = NULL; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key* keys; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fd; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off_t filesize; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Header header; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = open(filename, O_RDONLY); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == -1) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Can't open keycharmap file"); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filesize = lseek(fd, 0, SEEK_END); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lseek(fd, 0, SEEK_SET); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // validate the header 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (filesize <= (off_t)sizeof(header)) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Bad keycharmap - filesize=%d\n", (int)filesize); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = read(fd, &header, sizeof(header)); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == -1) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Error reading keycharmap file"); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (0 != memcmp(header.magic, "keychar", 8)) { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Bad keycharmap magic token"); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (header.endian != 0x12345678) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Bad keycharmap endians"); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((header.version & 0xff) != 2) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Only support keycharmap version 2 (got 0x%08x)", header.version); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (filesize < (off_t)(sizeof(Header)+(sizeof(Key)*header.keycount))) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Bad keycharmap file size\n"); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read the key data 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keys = (Key*)malloc(sizeof(Key)*header.keycount); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = read(fd, keys, sizeof(Key)*header.keycount); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == -1) { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("Error reading keycharmap file"); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(keys); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto cleanup1; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // return the object 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv = new KeyCharacterMap; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv->m_keyCount = header.keycount; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv->m_keys = keys; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rv->m_type = header.kbdtype; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectcleanup1: 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(fd); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rv; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 264