aboutsummaryrefslogtreecommitdiffstats
path: root/util/av7110_loadkeys/av7110_loadkeys.c
blob: 793862fd3355be2e6ba69417e927fab8993bba97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.Stri
#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;
	const struct input_key_name *kn;
	int r;

	if (limit < 5)
		return -1;

	while ((*pos == ' ' || *pos == '\t') && limit > 0) {
		(*nend)++;
		pos++;
		limit--;
	}

	if (pos[3] != '_')
		return -2;

	if (pos[0] == 'K' && pos[1] == 'E' && pos[2] == 'Y') {
		kn = key_name;
		r = sizeof (key_name) / sizeof (key_name[0]);
	}
	else if (pos[0] == 'B' && pos[1] == 'T' && pos[2] == 'N') {
		kn = btn_name;
		r = sizeof (btn_name) / sizeof (btn_name[0]);
	}
	else
		return -2;

	(*nend) += 4;
	pos += 4;
	limit -= 4;

	while (r >= l) {
		int len0, len1 = 0;

		_index = (l + r) / 2;

		len0 = strlen(kn[_index-1].name);

		while (len1 < limit && isgraph(pos[len1]))
			len1++;

		cmp = strncmp (kn[_index-1].name, pos,
			       strlen(kn[_index-1].name));

		if (len0 < len1 && cmp == 0)
			cmp = -1;

		if (cmp == 0) {
			*nend = pos + strlen (kn[_index-1].name);

			if (**nend != '\n' &&
			    **nend != '\t' &&
			    **nend != ' ' &&
			    *nend != pos)
				return -3;

			return kn[_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;
}