diff options
author | Sean Young <sean@mess.org> | 2019-08-26 11:52:35 +0100 |
---|---|---|
committer | Sean Young <sean@mess.org> | 2019-08-27 12:31:23 +0100 |
commit | 5effec906412efa6e4ba4726e8baf46cc8711a2b (patch) | |
tree | 9a73e26fdb2698742f5dbf8c6fe2c9a2a1bd1a01 /utils/keytable/keymap.c | |
parent | 83bfb96dc35e103854ef9494dd996b85261bb449 (diff) |
ir-ctl: send keys based on keymap
ir-ctl can now send keys based on rc keymaps. The keymap file must be
specified and the keys to be sent:
ir-ctl -k /lib/udev/rc_keymaps/hauppauge.toml -K KEY_VOLUMEUP
Signed-off-by: Sean Young <sean@mess.org>
Diffstat (limited to 'utils/keytable/keymap.c')
l---------[-rw-r--r--] | utils/keytable/keymap.c | 460 |
1 files changed, 1 insertions, 459 deletions
diff --git a/utils/keytable/keymap.c b/utils/keytable/keymap.c index bb193131..973bd380 100644..120000 --- a/utils/keytable/keymap.c +++ b/utils/keytable/keymap.c @@ -1,459 +1 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -// Read a toml keymap or plain text keymap (ir-keytable 1.14 or earlier -// format). - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <limits.h> -#include <stdbool.h> - -#include "keymap.h" -#include "toml.h" - -#ifdef ENABLE_NLS -# define _(string) gettext(string) -# include "gettext.h" -# include <locale.h> -# include <langinfo.h> -# include <iconv.h> -#else -# define _(string) string -#endif - -void free_keymap(struct keymap *map) -{ - struct scancode_entry *se; - struct raw_entry *re; - struct protocol_param *param; - struct keymap *next; - - while (map) { - re = map->raw; - - while (re) { - struct raw_entry *next = re->next; - free(re->keycode); - free(re); - re = next; - } - - - se = map->scancode; - - while (se) { - struct scancode_entry *next = se->next; - free(se->keycode); - free(se); - se = next; - } - - param = map->param; - - while (param) { - struct protocol_param *next = param->next; - free(param->name); - free(param); - param = next; - } - - next = map->next; - - free(map->name); - free(map->protocol); - free(map->variant); - free(map); - - map = next; - } -} - -static error_t parse_plain_keyfile(char *fname, struct keymap **keymap, bool verbose) -{ - FILE *fin; - int line = 0; - char *scancode, *keycode, s[2048]; - struct scancode_entry *se; - struct keymap *map; - - map = calloc(1, sizeof(*map)); - if (!map) { - perror("parse_keyfile"); - return ENOMEM; - } - - if (verbose) - fprintf(stderr, _("Parsing %s keycode file as plain text\n"), fname); - - fin = fopen(fname, "r"); - if (!fin) { - return errno; - } - - while (fgets(s, sizeof(s), fin)) { - char *p = s; - - line++; - while (*p == ' ' || *p == '\t') - p++; - if (line==1 && p[0] == '#') { - p++; - p = strtok(p, "\n\t =:"); - do { - if (!p) - goto err_einval; - if (!strcmp(p, "table")) { - p = strtok(NULL,"\n, "); - if (!p) - goto err_einval; - map->name = strdup(p); - } else if (!strcmp(p, "type")) { - p = strtok(NULL, " ,\n"); - if (!p) - goto err_einval; - - while (p) { - if (map->protocol) { - map->protocol = strdup(p); - } else { - struct keymap *k; - - k = calloc(1, sizeof(k)); - k->protocol = strdup(p); - k->next = map->next; - map->next = k; - } - - p = strtok(NULL, " ,\n"); - } - } else { - goto err_einval; - } - p = strtok(NULL, "\n\t =:"); - } while (p); - continue; - } - - if (*p == '\n' || *p == '#') - continue; - - scancode = strtok(p, "\n\t =:"); - if (!scancode) - goto err_einval; - if (!strcasecmp(scancode, "scancode")) { - scancode = strtok(NULL, "\n\t =:"); - if (!scancode) - goto err_einval; - } - - keycode = strtok(NULL, "\n\t =:("); - if (!keycode) - goto err_einval; - - se = calloc(1, sizeof(*se)); - if (!se) { - free_keymap(map); - perror("parse_keyfile"); - fclose(fin); - return ENOMEM; - } - - se->scancode = strtoul(scancode, NULL, 0); - se->keycode = keycode; - se->next = map->scancode; - map->scancode = se; - } - fclose(fin); - - *keymap = map; - - return 0; - -err_einval: - free_keymap(map); - fprintf(stderr, _("Invalid parameter on line %d of %s\n"), - line, fname); - return EINVAL; -} - -static error_t parse_toml_raw_part(const char *fname, struct toml_array_t *raw, struct keymap *map) -{ - struct toml_table_t *t; - struct toml_array_t *rawarray; - struct raw_entry *re; - const char *rkeycode; - int ind = 0, length; - char *keycode; - - while ((t = toml_table_at(raw, ind++)) != NULL) { - rkeycode = toml_raw_in(t, "keycode"); - if (!rkeycode) { - fprintf(stderr, _("%s: invalid keycode for raw entry %d\n"), - fname, ind); - return EINVAL; - } - - if (toml_rtos(rkeycode, &keycode)) { - fprintf(stderr, _("%s: bad value `%s' for keycode\n"), - fname, rkeycode); - return EINVAL; - } - - rawarray = toml_array_in(t, "raw"); - if (!rawarray) { - fprintf(stderr, _("%s: missing raw array for entry %d\n"), - fname, ind); - return EINVAL; - } - - // determine length of array - length = 0; - while (toml_raw_at(rawarray, length) != NULL) - length++; - - if (!(length % 2)) { - fprintf(stderr, _("%s: raw array must have odd length rather than %d\n"), - fname, length); - return EINVAL; - } - - re = calloc(1, sizeof(*re) + sizeof(re->raw[0]) * length); - if (!re) { - fprintf(stderr, _("Failed to allocate memory")); - return EINVAL; - } - - for (int i=0; i<length; i++) { - const char *s = toml_raw_at(rawarray, i); - int64_t v; - - if (toml_rtoi(s, &v) || v == 0) { - fprintf(stderr, _("%s: incorrect raw value `%s'"), - fname, s); - return EINVAL; - } - - if (v <= 0 || v > USHRT_MAX) { - fprintf(stderr, _("%s: raw value %ld out of range"), - fname, v); - return EINVAL; - } - - re->raw[i] = v; - } - - re->raw_length = length; - re->keycode = keycode; - re->next = map->raw; - map->raw = re; - } - - return 0; -} - - -static error_t parse_toml_protocol(const char *fname, struct toml_table_t *proot, struct keymap **keymap, bool verbose) -{ - struct toml_table_t *scancodes; - struct toml_array_t *rawarray; - const char *raw, *key; - bool have_raw_protocol = false; - struct keymap *map; - char *p; - int i = 0; - - map = calloc(1, sizeof(*map)); - if (!map) { - perror("parse_toml_protocol"); - return ENOMEM; - } - *keymap = map; - - raw = toml_raw_in(proot, "protocol"); - if (!raw) { - fprintf(stderr, _("%s: protocol missing\n"), fname); - return EINVAL; - } - - if (toml_rtos(raw, &p)) { - fprintf(stderr, _("%s: bad value `%s' for protocol\n"), fname, raw); - return EINVAL; - } - - map->protocol = strdup(p); - if (!strcmp(p, "raw")) - have_raw_protocol = true; - - raw = toml_raw_in(proot, "variant"); - if (raw) { - if (toml_rtos(raw, &p)) { - fprintf(stderr, _("%s: bad value `%s' for variant\n"), fname, raw); - return EINVAL; - } - - map->variant = strdup(p); - } - - raw = toml_raw_in(proot, "name"); - if (raw) { - if (toml_rtos(raw, &p)) { - fprintf(stderr, _("%s: bad value `%s' for name\n"), fname, raw); - return EINVAL; - } - - map->name = strdup(p); - } - - rawarray = toml_array_in(proot, "raw"); - if (rawarray) { - if (toml_raw_in(proot, "scancodes")) { - fprintf(stderr, _("Cannot have both [raw] and [scancode] sections")); - return EINVAL; - } - if (!have_raw_protocol) { - fprintf(stderr, _("Keymap with raw entries must have raw protocol")); - return EINVAL; - } - error_t err = parse_toml_raw_part(fname, rawarray, map); - if (err != 0) - return err; - - } else if (have_raw_protocol) { - fprintf(stderr, _("Keymap with raw protocol must have raw entries")); - return EINVAL; - } - - scancodes = toml_table_in(proot, "scancodes"); - if (!scancodes) { - if (verbose) - fprintf(stderr, _("%s: no [protocols.scancodes] section\n"), fname); - return 0; - } - - for (i = 0; (key = toml_key_in(proot, i)) != NULL; i++) { - long int value; - - raw = toml_raw_in(proot, key); - if (!toml_rtoi(raw, &value)) { - struct protocol_param *param; - - param = malloc(sizeof(*param)); - param->name = strdup(key); - param->value = value; - param->next = map->param; - map->param = param; - if (verbose) - fprintf(stderr, _("%s: protocol parameter %s=%ld\n"), fname, param->name, param->value); - } - } - - for (;;) { - struct scancode_entry *se; - const char *scancode; - char *keycode; - - scancode = toml_key_in(scancodes, i++); - if (!scancode) - break; - - raw = toml_raw_in(scancodes, scancode); - if (!raw) { - fprintf(stderr, _("%s: invalid value `%s'\n"), fname, scancode); - return EINVAL; - } - - if (toml_rtos(raw, &keycode)) { - fprintf(stderr, _("%s: bad value `%s' for keycode\n"), - fname, keycode); - return EINVAL; - } - - se = calloc(1, sizeof(*se)); - if (!se) { - perror("parse_keyfile"); - return ENOMEM; - } - - se->scancode = strtoul(scancode, NULL, 0); - se->keycode = keycode; - se->next = map->scancode; - map->scancode = se; - } - - return 0; -} - -static error_t parse_toml_keyfile(char *fname, struct keymap **keymap, bool verbose) -{ - struct toml_table_t *root, *proot; - struct toml_array_t *arr; - int ret, i = 0; - char buf[200]; - FILE *fin; - - if (verbose) - fprintf(stderr, _("Parsing %s keycode file as toml\n"), fname); - - fin = fopen(fname, "r"); - if (!fin) - return errno; - - root = toml_parse_file(fin, buf, sizeof(buf)); - fclose(fin); - if (!root) { - fprintf(stderr, _("%s: failed to parse toml: %s\n"), fname, buf); - return EINVAL; - } - - arr = toml_array_in(root, "protocols"); - if (!arr) { - fprintf(stderr, _("%s: missing [protocols] section\n"), fname); - return EINVAL; - } - - struct keymap *map = NULL; - - for (;;) { - struct keymap *cur_map; - - proot = toml_table_at(arr, i); - if (!proot) - break; - - ret = parse_toml_protocol(fname, proot, &cur_map, verbose); - if (ret) - goto out; - - if (!map) { - map = cur_map; - } else { - cur_map->next = map->next; - map->next = cur_map; - } - i++; - } - - if (i == 0) { - fprintf(stderr, _("%s: no protocols found\n"), fname); - goto out; - } - - toml_free(root); - *keymap = map; - return 0; -out: - toml_free(root); - return EINVAL; -} - -error_t parse_keyfile(char *fname, struct keymap **keymap, bool verbose) -{ - size_t len = strlen(fname); - - if (len >= 5 && strcasecmp(fname + len - 5, ".toml") == 0) - return parse_toml_keyfile(fname, keymap, verbose); - else - return parse_plain_keyfile(fname, keymap, verbose); -} +../common/keymap.c
\ No newline at end of file |