diff options
Diffstat (limited to 'util/av7110_loadkeys/av7110_loadkeys.c')
-rw-r--r-- | util/av7110_loadkeys/av7110_loadkeys.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/util/av7110_loadkeys/av7110_loadkeys.c b/util/av7110_loadkeys/av7110_loadkeys.c new file mode 100644 index 0000000..e9eeea0 --- /dev/null +++ b/util/av7110_loadkeys/av7110_loadkeys.c @@ -0,0 +1,186 @@ +#include <asm/types.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> +#include <string.h> + +#include "input_keynames.h" + + +static +void print_error (const char *action, const char *file) +__attribute__ ((noreturn)); + + +static +void print_error (const char *action, const char *file) +{ + static const char msg [] = "\nERROR: could not "; + + write (0, msg, strlen(msg)); + write (0, action, strlen(action)); + write (0, " '", 2); + write (0, file, strlen(file)); + write (0, "'\n\n", 3); + exit (-1); +} + + +static +int parse_keyname (char *pos, char **nend, int limit) +{ + int cmp, index; + int l = 1; + int r = sizeof (key_name) / sizeof (key_name[0]); + + if (limit < 5) + return -1; + + while ((*pos == ' ' || *pos == '\t') && limit > 0) { + (*nend)++; + pos++; + limit--; + } + + if (pos [0] != 'K' || pos[1] != 'E' || pos[2] != 'Y' || pos[3] != '_') + return -2; + + (*nend) += 4; + pos += 4; + limit -= 4; + + while (r >= l) { + int len0, len1 = 0; + + index = (l + r) / 2; + + len0 = strlen(key_name[index-1].name); + + while (len1 < limit && isgraph(pos[len1])) + len1++; + + cmp = strncmp (key_name[index-1].name, pos, + strlen(key_name[index-1].name)); + + if (len0 < len1 && cmp == 0) + cmp = -1; + + if (cmp == 0) { + *nend = pos + strlen (key_name[index-1].name); + + if (**nend != '\n' && + **nend != '\t' && + **nend != ' ' && + *nend != pos) + return -3; + + return key_name[index-1].key; + } + + if (cmp < 0) + l = index + 1; + else + r = index - 1; + + if (r < l) { + static const char msg [] = "\nunknown key '"; + write (0, msg, strlen(msg)); + write (0, pos-4, len1 + 4); + write (0, "'\n", 2); + } + }; + + return -4; +} + + + +const char usage [] = "\n\tusage: av7110_loadkeys [-i|--invert] [-a|--address <num>] keymap_filename.(rc5|rcmm)\n\n"; + + +struct ir_setup { + __u32 ir_config; + __u16 keytab [256]; +} __attribute__ ((packed)); + + +int main (int argc, char **argv) +{ + static struct ir_setup setup; + int i, fd; + size_t len; + char *buf, *pos, *fname = NULL; + + for (i=1; i<argc; i++) { + if (!strcmp("-i", argv[i]) || !strcmp("--invert", argv[i])) + setup.ir_config |= 0x8000; + else if (!strcmp("-a", argv[i]) || !strcmp("--address", argv[i])) { + if (++i < argc) { + setup.ir_config |= (atoi(argv[i]) & 0xff) << 16; + setup.ir_config |= 0x4000; + } + } else + fname = argv[i]; + } + + if (!fname) { + write (0, usage, strlen(usage)); + exit (-1); + } + + if (strncmp(".rcmm", fname + strlen(fname) - 5, 5) == 0) + setup.ir_config |= 0x0001; + else if (strncmp(".rc5", fname + strlen(fname) - 4, 4) != 0) { + const char msg [] = "\nERROR: " + "input filename must have suffix .rc5 or .rcmm\n"; + write (0, msg, strlen(msg)); + exit (-1); + } + + if ((fd = open (fname, O_RDONLY)) < 0) + print_error ("open", fname); + + len = lseek (fd, 0, SEEK_END); + + if (!(pos = buf = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, 0))) + print_error ("mmap", fname); + + while (pos < buf + len) { + int key, keycode; + + while (!isxdigit(*pos) && pos < buf + len) + pos++; + + if (pos == buf + len) + break; + + key = strtol (pos, &pos, 0); + keycode = parse_keyname (pos, &pos, buf + len - pos); + + if (key < 0 || key > 0xff) { + const char msg [] = + "\nERROR: key must be in range 0 ... 0xff!\n\n"; + + write (0, msg, strlen(msg)); + exit (-1); + } + + if (keycode < 0) + print_error ("parse", fname); + + setup.keytab[key] = keycode; + } + + munmap (buf, len); + close (fd); + + write (1, &setup, 4 + 256 * sizeof(__u16)); + + return 0; +} + + |