// gcc -o generator generator.c -lxkbcommon #include #include #include #include #include #include #include #include #include #include "evdev-keycodes.h" #include "log.h" #include "android-keycodes.h" #define KEYCODE_MIN 8 #define KEYCODE_MAX 255 #define EVDEV_OFFSET 8 #define SYM_LENGTH 7 int android_keycode_to_linux_event_code(int keyCode, int *eventCode, int *shift); struct keysym { int eventCode; char normal[SYM_LENGTH]; char shift[SYM_LENGTH]; }; #define KEYMAPS_LENGTH 1 struct keymap { char *name; struct keysym keysyms[KEYCODE_MAX - KEYCODE_MIN]; } keymaps[KEYMAPS_LENGTH] = {0}; void handler(int sig) { void *array[10]; size_t size; // get void*'s for all entries on the stack size = backtrace(array, 10); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, STDERR_FILENO); exit(1); } #define K(c1, c2) case EVDEV_##c1: return KEY_##c2 int keyCode2eventCode(int kc) { int keyCode = kc - KEYCODE_MIN; switch(keyCode) { K(TLDE, GRAVE); K(AE01, 1); K(AE02, 2); K(AE03, 3); K(AE04, 4); K(AE05, 5); K(AE06, 6); K(AE07, 7); K(AE08, 8); K(AE09, 9); K(AE10, 0); K(AE11, MINUS); K(AE12, EQUAL); K(BKSP, BACKSPACE); K(TAB, TAB); K(AD01, Q); K(AD02, W); K(AD03, E); K(AD04, R); K(AD05, T); K(AD06, Y); K(AD07, U); K(AD08, I); K(AD09, O); K(AD10, P); K(AD11, LEFTBRACE); K(AD12, RIGHTBRACE); //K(BKSL, BACKSLASH); // DUPLICATE K(RTRN, ENTER); K(CAPS, CAPSLOCK); K(AC01, A); K(AC02, S); K(AC03, D); K(AC04, F); K(AC05, G); K(AC06, H); K(AC07, J); K(AC08, K); K(AC09, L); K(AC10, SEMICOLON); K(AC11, APOSTROPHE); K(AC12, BACKSLASH); K(LFSH, LEFTSHIFT); K(AB01, Z); K(AB02, X); K(AB03, C); K(AB04, V); K(AB05, B); K(AB06, N); K(AB07, M); K(AB08, COMMA); K(AB09, DOT); K(AB10, SLASH); K(RTSH, RIGHTSHIFT); default: return KEY_UNKNOWN; } return KEY_UNKNOWN; } struct iterator_args { struct keymap *keymap; uint8_t symcase; }; void iterate_normal(struct xkb_keymap *xkb_keymap, xkb_keycode_t key, void *data) { struct iterator_args *ita = data; if (!ita || !ita->keymap) return; struct keymap *keymap = ita->keymap; struct xkb_state *xkb_state = NULL; char *buf = NULL; xkb_keysym_t ks = 0; xkb_state = xkb_state_new(xkb_keymap); if (xkb_state == NULL) { LOGE("failed to create xkb_state"); }; if (ita->symcase) { xkb_state_update_key(xkb_state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); buf = keymap->keysyms[key].shift; } else { buf = keymap->keysyms[key].normal; } ks = xkb_state_key_get_one_sym(xkb_state, key); xkb_keysym_to_utf8(ks, buf, SYM_LENGTH); xkb_state_unref(xkb_state); } struct keymap* parse_keymap(struct xkb_context *ctx, char *name) { if (!ctx || !name) return NULL; struct xkb_rule_names xkb_names = {0}; struct xkb_keymap *xkb_keymap = NULL; struct iterator_args ita = {0}; struct keymap *result = NULL; xkb_names.rules = strdup("evdev"); xkb_names.model = strdup("pc105"); xkb_names.layout = strdup(name); xkb_keymap = xkb_keymap_new_from_names(ctx, &xkb_names, 0); if (xkb_keymap == NULL) { LOGE("failed to compile global XKB keymap\n"); LOGE(" tried rules %s, model %s, layout %s, variant %s, " "options %s\n", xkb_names.rules, xkb_names.model, xkb_names.layout, xkb_names.variant, xkb_names.options); goto end; } result = calloc(1, sizeof(struct keymap)); if (!result) { LOGE("failed to allocate struct keymap"); goto end; } result->name = strdup(name); ita.keymap = result; ita.symcase = 0; xkb_keymap_key_for_each(xkb_keymap, iterate_normal, &ita); ita.symcase = 1; xkb_keymap_key_for_each(xkb_keymap, iterate_normal, &ita); for (int i=0; i<(KEYCODE_MAX-KEYCODE_MIN);i++) result->keysyms[i].eventCode = keyCode2eventCode(i+KEYCODE_MIN); end: if (xkb_keymap) xkb_keymap_unref(xkb_keymap); if (xkb_names.rules) free((void*)xkb_names.rules); if (xkb_names.model) free((void*)xkb_names.model); if (xkb_names.layout) free((void*)xkb_names.layout); return result; } void print_header(void) { printf( "#include \n" "#define SYM_LENGTH %d\n" "#define KEYCODE_MIN 8\n" "#define KEYCODE_MAX 255\n" "#define NOSYM {{0}, {0}}\n" "struct lorie_keymap {\n" "\tchar *name;\n" "\tstruct keysym {\n" "\t\tchar normal[SYM_LENGTH];\n" "\t\tchar shift[SYM_LENGTH];\n" "\t} keysyms[KEYCODE_MAX - KEYCODE_MIN];\n" "};\n\n", SYM_LENGTH ); } void print_sym(char *sym) { int i; if (strlen(sym)) { printf("{"); for(i=0; i 0 && i < SYM_LENGTH) printf(", "); printf("%d", (inormal) && strlen(keysym->shift)) { printf("\t\t{"); print_sym(keysym->normal); printf(", "); print_sym(keysym->shift); printf("}"); } else printf("\t\tNOSYM"); } int ks_displayable(char *sym) { if (strlen(sym) == 0) return 0; if (strlen(sym) == 1) { switch(sym[0]) { case 8: case 10: case 13: case 27: case 30: case 127: return 0; } } return 1; } int find_keysym_by_eventcode(struct keymap* keymap, int eventCode) { for (int i=0; i<(KEYCODE_MAX-KEYCODE_MIN); i++) { if (keymap->keysyms[i].eventCode == eventCode) return i; } return -1; } void keymap_print(struct keymap* keymap) { if (!keymap) return; int i, j, latestEventCode; printf( "struct lorie_keymap lorie_keymap_%s = {\n" "\t.name = (char*) \"%s\",\n" "\t.keysyms = {\n", keymap->name, keymap->name ); #if 0 for (i=0; i<(KEYCODE_MAX-KEYCODE_MIN); i++) { print_keysym(&keymap->keysyms[i]); if (i!=(KEYCODE_MAX-KEYCODE_MIN-1)) printf(","); printf(" // keyCode: %d; eventCode: %d;", i + KEYCODE_MIN, keymap->keysyms[i].eventCode); if (ks_displayable(i, keymap->keysyms[i].normal)) printf(" normal: \"%s\";", keymap->keysyms[i].normal); if (ks_displayable(i, keymap->keysyms[i].shift)) printf(" shift: \"%s\";", keymap->keysyms[i].shift); printf("\n"); } #else latestEventCode = 0; for (i=0; i<(KEYCODE_MAX-KEYCODE_MIN); i++) { if (keymap->keysyms[i].eventCode > latestEventCode && keymap->keysyms[i].eventCode != KEY_UNKNOWN && strlen(keymap->keysyms[i].normal) && strlen(keymap->keysyms[i].shift)) // check if it is displayable and known latestEventCode = keymap->keysyms[i].eventCode; } //printf("\n\n\nLatest eventCode = %d\n\n\n\n", latestEventCode); for (i=0; i<=latestEventCode; i++) { j = find_keysym_by_eventcode(keymap, i); struct keysym* k = &keymap->keysyms[j]; if (j >= 0) { print_keysym(k); if (j!=(KEYCODE_MAX-KEYCODE_MIN-1)) printf(","); printf(" // eventCode: %d;", i); if (ks_displayable(k->normal)) printf(" normal: \"%s\";", k->normal); if (ks_displayable(k->shift)) printf(" shift: \"%s\";", k->shift); printf("\n"); } else printf("\t\tNOSYM, // eventCode: %d\n", i); } #endif printf("\t}\n};\n"); } int main(void) { signal(SIGSEGV, handler); int i; struct xkb_context *xkb_context = NULL; struct xkb_rule_names xkb_names = {0}; struct xkb_keymap *xkb_keymap = NULL; struct keymap* map = NULL; //char *keymaps[] = { "us", NULL }; //char *keymaps[] = { "ru", "il", NULL }; char *keymaps[] = { "ru", NULL }; if (xkb_context == NULL) { xkb_context = xkb_context_new(0); if (xkb_context == NULL) { LOGE("failed to create XKB context\n"); return 1; } } print_header(); for (i=0; keymaps[i]; i++) { map = parse_keymap(xkb_context, keymaps[i]); if (!map) { LOGE("failed to parse keymap \"us\""); return 1; } keymap_print(map); } printf("\nstruct lorie_keymap *lorie_keymaps[] = {"); for (i=0; keymaps[i]; i++) { printf("&lorie_keymap_%s, ", keymaps[i]); } printf("NULL};\n\n"); printf("struct lorie_keymap_android {\n"); printf("\tint eventCode;\n"); printf("\tint shift;\n"); printf("} lorie_keymap_android[] = {\n"); int lastWasNull = 0; for (i=0; i<=ANDROID_KEYCODE_LAST; i++) { int evCode = 0; int shift = 0; if (android_keycode_to_linux_event_code(i, &evCode, &shift)) { if (lastWasNull) printf("\n"); printf("\t{%d, %d}%s // keycode %d\n", evCode, shift, (i!=ANDROID_KEYCODE_LAST)?",":"", i); lastWasNull = 0; } else { if (!lastWasNull) printf("\t"); printf("{0, 0}%s", (i!=ANDROID_KEYCODE_LAST)?", ":"\n"); lastWasNull = 1; } }; printf("};\n"); }