aboutsummaryrefslogtreecommitdiffstats
path: root/util/av7110_loadkeys/av7110_loadkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/av7110_loadkeys/av7110_loadkeys.c')
-rw-r--r--util/av7110_loadkeys/av7110_loadkeys.c186
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;
+}
+
+