18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU keysym to keycode conversion using rdesktop keymaps 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2004 Johannes Schindelin 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions: 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software. 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE. 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "keymaps.h" 2634c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h" 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int get_keysym(const name2keysym_t *table, 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name) 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const name2keysym_t *p; 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(p = table; p->name != NULL; p++) { 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!strcmp(p->name, name)) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return p->keysym; 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void add_to_key_range(struct key_range **krp, int code) { 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct key_range *kr; 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (kr = *krp; kr; kr = kr->next) { 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (code >= kr->start && code <= kr->end) 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (code == kr->start - 1) { 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kr->start--; 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (code == kr->end + 1) { 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kr->end++; 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (kr == NULL) { 55aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner kr = g_malloc0(sizeof(*kr)); 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kr->start = kr->end = code; 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner kr->next = *krp; 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *krp = kr; 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table, 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *language, 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_layout_t * k) 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FILE *f; 67cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine /* This file is used by both, UI and core components. There are differences 68cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine * in the way how keymap file path is obtained for these two different 69cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine * configurations. */ 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char * filename; 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char line[1024]; 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len; 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner filename = qemu_find_file(QEMU_FILE_TYPE_KEYMAP, language); 75cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine if (!filename) { 76cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine fprintf(stderr, 77cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine "Could not read keymap file: '%s'\n", language); 78cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine return NULL; 79cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine } 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!k) 82aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner k = g_malloc0(sizeof(kbd_layout_t)); 83cefa7443eb3d3e4bb134595f756145426d5613e3Vladimir Chtchetkine if (!(f = fopen(filename, "r"))) { 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "Could not read keymap file: '%s'\n", language); 862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return NULL; 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(;;) { 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (fgets(line, 1024, f) == NULL) 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = strlen(line); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > 0 && line[len - 1] == '\n') 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project line[len - 1] = '\0'; 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (line[0] == '#') 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!strncmp(line, "map ", 4)) 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!strncmp(line, "include ", 8)) { 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner parse_keyboard_layout(table, line + 8, k); 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *end_of_keysym = line; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (*end_of_keysym != 0 && *end_of_keysym != ' ') 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project end_of_keysym++; 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (*end_of_keysym) { 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int keysym; 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *end_of_keysym = 0; 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner keysym = get_keysym(table, line); 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keysym == 0) { 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // fprintf(stderr, "Warning: unknown keysym %s\n", line); 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const char *rest = end_of_keysym + 1; 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *rest2; 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int keycode = strtol(rest, &rest2, 0); 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rest && strstr(rest, "numlock")) { 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project add_to_key_range(&k->keypad_range, keycode); 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project add_to_key_range(&k->numlock_range, keysym); 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode); 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if(keycode&0x80) 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keycode=(keycode<<8)^0x80e0; */ 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keysym < MAX_NORMAL_KEYCODE) { 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode); 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project k->keysym2keycode[keysym] = keycode; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (k->extra_count >= MAX_EXTRA_COUNT) { 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "Warning: Could not assign keysym %s (0x%x) because of memory constraints.\n", 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project line, keysym); 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "Setting %d: %d,%d\n", 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project k->extra_count, keysym, keycode); 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project k->keysym2keycode_extra[k->extra_count]. 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keysym = keysym; 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project k->keysym2keycode_extra[k->extra_count]. 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keycode = keycode; 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project k->extra_count++; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fclose(f); 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return k; 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *init_keyboard_layout(const name2keysym_t *table, const char *language) 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return parse_keyboard_layout(table, language, NULL); 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint keysym2scancode(void *kbd_layout, int keysym) 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_layout_t *k = kbd_layout; 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keysym < MAX_NORMAL_KEYCODE) { 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (k->keysym2keycode[keysym] == 0) 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "Warning: no scancode found for keysym %d\n", 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keysym); 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return k->keysym2keycode[keysym]; 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef XK_ISO_Left_Tab 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keysym == XK_ISO_Left_Tab) 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project keysym = XK_Tab; 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < k->extra_count; i++) 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (k->keysym2keycode_extra[i].keysym == keysym) 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return k->keysym2keycode_extra[i].keycode; 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint keycode_is_keypad(void *kbd_layout, int keycode) 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_layout_t *k = kbd_layout; 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct key_range *kr; 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (kr = k->keypad_range; kr; kr = kr->next) 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keycode >= kr->start && keycode <= kr->end) 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint keysym_is_numlock(void *kbd_layout, int keysym) 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project kbd_layout_t *k = kbd_layout; 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct key_range *kr; 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (kr = k->numlock_range; kr; kr = kr->next) 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (keysym >= kr->start && keysym <= kr->end) 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 200