* [PATCH 0/4] Add protocol support to ir-keytable
@ 2015-04-06 11:25 David Härdeman
2015-04-06 11:26 ` [PATCH 1/4] ir-keytable: clarify the meaning of ir protocols David Härdeman
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: David Härdeman @ 2015-04-06 11:25 UTC (permalink / raw)
To: linux-media; +Cc: m.chehab
The following series adds support to ir-keytable for explicitly
setting the protocol of scancode<->keycode mappings (requires
a patched kernel).
The first three patches are cleanups and refactoring which are
probably worthwhile to apply in any case.
The fourth patch adds the actual support (backward compatible) for
set-key and reading the keytable. Separate patches would be necessary
to also support reading keytable files with protocol information.
---
David Härdeman (4):
ir-keytable: clarify the meaning of ir protocols
ir-keytable: replace more sysfs if-else code with loops
ir-keytable: cleanup keytable code
ir-keytable: allow protocol for scancode-keycode mappings
utils/keytable/keytable.c | 716 +++++++++++++++++++++++----------------------
1 file changed, 364 insertions(+), 352 deletions(-)
--
David Härdeman
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] ir-keytable: clarify the meaning of ir protocols
2015-04-06 11:25 [PATCH 0/4] Add protocol support to ir-keytable David Härdeman
@ 2015-04-06 11:26 ` David Härdeman
2015-04-06 11:26 ` [PATCH 2/4] ir-keytable: replace more sysfs if-else code with loops David Härdeman
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: David Härdeman @ 2015-04-06 11:26 UTC (permalink / raw)
To: linux-media; +Cc: m.chehab
Clarify that ir protocols refer to the ones used by sysfs (e.g. "sony", not
"sony12" or "sony15") and replace a bunch of if-else protocol comparison
code with loops instead.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
utils/keytable/keytable.c | 408 +++++++++++++++++----------------------------
1 file changed, 152 insertions(+), 256 deletions(-)
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index dcbfd83..2ca693f 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <dirent.h>
#include <argp.h>
+#include <stdbool.h>
#include "parse.h"
@@ -89,21 +90,88 @@ enum sysfs_ver {
VERSION_2, /* has node protocols */
};
-enum ir_protocols {
- RC_5 = 1 << 0,
- RC_6 = 1 << 1,
- NEC = 1 << 2,
- JVC = 1 << 3,
- SONY = 1 << 4,
- LIRC = 1 << 5,
- SANYO = 1 << 6,
- RC_5_SZ = 1 << 7,
- SHARP = 1 << 8,
- MCE_KBD = 1 << 9,
- XMP = 1 << 10,
- OTHER = 1 << 31,
+enum sysfs_protocols {
+ SYSFS_UNKNOWN = (1 << 0),
+ SYSFS_OTHER = (1 << 1),
+ SYSFS_LIRC = (1 << 2),
+ SYSFS_RC5 = (1 << 3),
+ SYSFS_RC5_SZ = (1 << 4),
+ SYSFS_JVC = (1 << 5),
+ SYSFS_SONY = (1 << 6),
+ SYSFS_NEC = (1 << 7),
+ SYSFS_SANYO = (1 << 8),
+ SYSFS_MCE_KBD = (1 << 9),
+ SYSFS_RC6 = (1 << 10),
+ SYSFS_SHARP = (1 << 11),
+ SYSFS_XMP = (1 << 12),
+ SYSFS_INVALID = 0,
};
+struct protocol_map_entry {
+ const char *name;
+ enum sysfs_protocols sysfs_protocol;
+};
+
+const struct protocol_map_entry protocol_map[] = {
+ { "unknown", SYSFS_UNKNOWN },
+ { "other", SYSFS_OTHER },
+ { "lirc", SYSFS_LIRC },
+ { "rc-5", SYSFS_RC5 },
+ { "rc5", SYSFS_RC5 },
+ { "rc-5x", SYSFS_INVALID },
+ { "rc5x", SYSFS_INVALID },
+ { "jvc", SYSFS_JVC },
+ { "sony", SYSFS_SONY },
+ { "sony12", SYSFS_INVALID },
+ { "sony15", SYSFS_INVALID },
+ { "sony20", SYSFS_INVALID },
+ { "nec", SYSFS_NEC },
+ { "sanyo", SYSFS_SANYO },
+ { "mce-kbd", SYSFS_MCE_KBD },
+ { "mce_kbd", SYSFS_MCE_KBD },
+ { "rc-6", SYSFS_RC6 },
+ { "rc6", SYSFS_RC6 },
+ { "rc-6-0", SYSFS_INVALID },
+ { "rc-6-6a-20", SYSFS_INVALID },
+ { "rc-6-6a-24", SYSFS_INVALID },
+ { "rc-6-6a-32", SYSFS_INVALID },
+ { "rc-6-mce", SYSFS_INVALID },
+ { "sharp", SYSFS_SHARP },
+ { "xmp", SYSFS_XMP },
+ { NULL, SYSFS_INVALID },
+};
+
+static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allowed)
+{
+ const struct protocol_map_entry *pme;
+
+ if (!name)
+ return SYSFS_INVALID;
+
+ if (all_allowed && !strcasecmp(name, "all"))
+ return ~0;
+
+ for (pme = protocol_map; pme->name; pme++) {
+ if (!strcasecmp(name, pme->name))
+ return pme->sysfs_protocol;
+ }
+
+ return SYSFS_INVALID;
+}
+
+static void write_sysfs_protocols(enum sysfs_protocols protocols, FILE *fp, const char *fmt)
+{
+ const struct protocol_map_entry *pme;
+
+ for (pme = protocol_map; pme->name; pme++) {
+ if (!(protocols & pme->sysfs_protocol))
+ continue;
+
+ fprintf(fp, fmt, pme->name);
+ protocols &= ~pme->sysfs_protocol;
+ }
+}
+
static int parse_code(char *string)
{
struct parse_event *p;
@@ -166,7 +234,7 @@ static int debug = 0;
static int test = 0;
static int delay = 0;
static int period = 0;
-static enum ir_protocols ch_proto = 0;
+static enum sysfs_protocols ch_proto = 0;
struct keytable keys = {
.codes = {0, 0},
@@ -196,7 +264,7 @@ struct rc_device {
enum sysfs_ver version; /* sysfs version */
enum rc_type type; /* Software (raw) or hardware decoder */
- enum ir_protocols supported, current; /* Current and supported IR protocols */
+ enum sysfs_protocols supported, current; /* Current and supported IR protocols */
};
struct keytable *nextkey = &keys;
@@ -237,37 +305,20 @@ static error_t parse_keyfile(char *fname, char **table)
strcpy(*table, p);
} else if (!strcmp(p, "type")) {
p = strtok(NULL, " ,\n");
- do {
- if (!p)
- goto err_einval;
- if (!strcasecmp(p,"rc5") || !strcasecmp(p,"rc-5"))
- ch_proto |= RC_5;
- else if (!strcasecmp(p,"rc6") || !strcasecmp(p,"rc-6") || !strcasecmp(p,"rc6-mce") || !strcasecmp(p,"rc6_mce"))
- ch_proto |= RC_6;
- else if (!strcasecmp(p,"nec"))
- ch_proto |= NEC;
- else if (!strcasecmp(p,"jvc"))
- ch_proto |= JVC;
- else if (!strcasecmp(p,"sony"))
- ch_proto |= SONY;
- else if (!strcasecmp(p,"sanyo"))
- ch_proto |= SANYO;
- else if (!strcasecmp(p,"rc-5-sz"))
- ch_proto |= RC_5_SZ;
- else if (!strcasecmp(p,"sharp"))
- ch_proto |= SHARP;
- else if (!strcasecmp(p,"mce-kbd"))
- ch_proto |= MCE_KBD;
- else if (!strcasecmp(p,"xmp"))
- ch_proto |= XMP;
- else if (!strcasecmp(p,"other") || !strcasecmp(p,"unknown"))
- ch_proto |= OTHER;
- else {
+ if (!p)
+ goto err_einval;
+
+ while (p) {
+ enum sysfs_protocols protocol;
+
+ protocol = parse_sysfs_protocol(p, false);
+ if (protocol == SYSFS_INVALID) {
fprintf(stderr, _("Protocol %s invalid\n"), p);
goto err_einval;
}
+ ch_proto |= protocol;
p = strtok(NULL, " ,\n");
- } while (p);
+ }
} else {
goto err_einval;
}
@@ -477,38 +528,15 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
} while (p);
break;
case 'p':
- p = strtok(arg, ",;");
- do {
- if (!p)
- goto err_inval;
- if (!strcasecmp(p,"rc5") || !strcasecmp(p,"rc-5"))
- ch_proto |= RC_5;
- else if (!strcasecmp(p,"rc6") || !strcasecmp(p,"rc-6"))
- ch_proto |= RC_6;
- else if (!strcasecmp(p,"nec"))
- ch_proto |= NEC;
- else if (!strcasecmp(p,"jvc"))
- ch_proto |= JVC;
- else if (!strcasecmp(p,"sony"))
- ch_proto |= SONY;
- else if (!strcasecmp(p,"sanyo"))
- ch_proto |= SANYO;
- else if (!strcasecmp(p,"lirc"))
- ch_proto |= LIRC;
- else if (!strcasecmp(p,"rc-5-sz"))
- ch_proto |= RC_5_SZ;
- else if (!strcasecmp(p,"sharp"))
- ch_proto |= RC_5_SZ;
- else if (!strcasecmp(p,"mce-kbd"))
- ch_proto |= RC_5_SZ;
- else if (!strcasecmp(p,"xmp"))
- ch_proto |= XMP;
- else if (!strcasecmp(p,"all"))
- ch_proto |= ~0;
- else
+ for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
+ enum sysfs_protocols protocol;
+
+ protocol = parse_sysfs_protocol(p, true);
+ if (protocol == SYSFS_INVALID)
goto err_inval;
- p = strtok(NULL, ",;");
- } while (p);
+
+ ch_proto |= protocol;
+ }
break;
case '?':
argp_state_help(state, state->out_stream,
@@ -754,11 +782,11 @@ static struct sysfs_names *find_device(char *name)
return names;
}
-static enum ir_protocols v1_get_hw_protocols(char *name)
+static enum sysfs_protocols v1_get_hw_protocols(char *name)
{
FILE *fp;
char *p, buf[4096];
- enum ir_protocols proto = 0;
+ enum sysfs_protocols protocols = 0;
fp = fopen(name, "r");
if (!fp) {
@@ -772,39 +800,22 @@ static enum ir_protocols v1_get_hw_protocols(char *name)
return 0;
}
- p = strtok(buf, " \n");
- while (p) {
+ for (p = strtok(buf, " \n"); p; p = strtok(NULL, " \n")) {
+ enum sysfs_protocols protocol;
+
if (debug)
fprintf(stderr, _("%s protocol %s\n"), name, p);
- if (!strcmp(p, "rc-5"))
- proto |= RC_5;
- else if (!strcmp(p, "rc-6"))
- proto |= RC_6;
- else if (!strcmp(p, "nec"))
- proto |= NEC;
- else if (!strcmp(p, "jvc"))
- proto |= JVC;
- else if (!strcmp(p, "sony"))
- proto |= SONY;
- else if (!strcmp(p, "sanyo"))
- proto |= SANYO;
- else if (!strcmp(p, "rc-5-sz"))
- proto |= RC_5_SZ;
- else if (!strcmp(p, "sharp"))
- proto |= SHARP;
- else if (!strcmp(p, "mce-kbd"))
- proto |= MCE_KBD;
- else if (!strcmp(p, "xmp"))
- proto |= XMP;
- else
- proto |= OTHER;
-
- p = strtok(NULL, " \n");
+
+ protocol = parse_sysfs_protocol(p, false);
+ if (protocol == SYSFS_INVALID)
+ protocol = SYSFS_OTHER;
+
+ protocols |= protocol;
}
fclose(fp);
- return proto;
+ return protocols;
}
static int v1_set_hw_protocols(struct rc_device *rc_dev)
@@ -821,38 +832,7 @@ static int v1_set_hw_protocols(struct rc_device *rc_dev)
return errno;
}
- if (rc_dev->current & RC_5)
- fprintf(fp, "rc-5 ");
-
- if (rc_dev->current & RC_6)
- fprintf(fp, "rc-6 ");
-
- if (rc_dev->current & NEC)
- fprintf(fp, "nec ");
-
- if (rc_dev->current & JVC)
- fprintf(fp, "jvc ");
-
- if (rc_dev->current & SONY)
- fprintf(fp, "sony ");
-
- if (rc_dev->current & SANYO)
- fprintf(fp, "sanyo ");
-
- if (rc_dev->current & RC_5_SZ)
- fprintf(fp, "rc-5-sz ");
-
- if (rc_dev->current & SHARP)
- fprintf(fp, "sharp ");
-
- if (rc_dev->current & MCE_KBD)
- fprintf(fp, "mce_kbd ");
-
- if (rc_dev->current & XMP)
- fprintf(fp, "xmp ");
-
- if (rc_dev->current & OTHER)
- fprintf(fp, "unknown ");
+ write_sysfs_protocols(rc_dev->current, fp, "%s ");
fprintf(fp, "\n");
@@ -934,12 +914,11 @@ static int v1_set_sw_enabled_protocol(struct rc_device *rc_dev,
return 0;
}
-static enum ir_protocols v2_get_protocols(struct rc_device *rc_dev, char *name)
+static enum sysfs_protocols v2_get_protocols(struct rc_device *rc_dev, char *name)
{
FILE *fp;
char *p, buf[4096];
int enabled;
- enum ir_protocols proto;
fp = fopen(name, "r");
if (!fp) {
@@ -953,8 +932,9 @@ static enum ir_protocols v2_get_protocols(struct rc_device *rc_dev, char *name)
return 0;
}
- p = strtok(buf, " \n");
- while (p) {
+ for (p = strtok(buf, " \n"); p; p = strtok(NULL, " \n")) {
+ enum sysfs_protocols protocol;
+
if (*p == '[') {
enabled = 1;
p++;
@@ -966,36 +946,14 @@ static enum ir_protocols v2_get_protocols(struct rc_device *rc_dev, char *name)
fprintf(stderr, _("%s protocol %s (%s)\n"), name, p,
enabled? _("enabled") : _("disabled"));
- if (!strcmp(p, "rc-5"))
- proto = RC_5;
- else if (!strcmp(p, "rc-6"))
- proto = RC_6;
- else if (!strcmp(p, "nec"))
- proto = NEC;
- else if (!strcmp(p, "jvc"))
- proto = JVC;
- else if (!strcmp(p, "sony"))
- proto = SONY;
- else if (!strcmp(p, "sanyo"))
- proto = SANYO;
- else if (!strcmp(p, "lirc")) /* Only V2 has LIRC support */
- proto = LIRC;
- else if (!strcmp(p, "rc-5-sz"))
- proto = RC_5_SZ;
- else if (!strcmp(p, "sharp"))
- proto = SHARP;
- else if (!strcmp(p, "mce-kbd"))
- proto = MCE_KBD;
- else if (!strcmp(p, "xmp"))
- proto = XMP;
- else
- proto = OTHER;
-
- rc_dev->supported |= proto;
+ protocol = parse_sysfs_protocol(p, false);
+ if (protocol == SYSFS_INVALID)
+ protocol = SYSFS_OTHER;
+
+ rc_dev->supported |= protocol;
if (enabled)
- rc_dev->current |= proto;
+ rc_dev->current |= protocol;
- p = strtok(NULL, " \n");
}
fclose(fp);
@@ -1020,41 +978,7 @@ static int v2_set_protocols(struct rc_device *rc_dev)
/* Disable all protocols */
fprintf(fp, "none\n");
- if (rc_dev->current & RC_5)
- fprintf(fp, "+rc-5\n");
-
- if (rc_dev->current & RC_6)
- fprintf(fp, "+rc-6\n");
-
- if (rc_dev->current & NEC)
- fprintf(fp, "+nec\n");
-
- if (rc_dev->current & JVC)
- fprintf(fp, "+jvc\n");
-
- if (rc_dev->current & SONY)
- fprintf(fp, "+sony\n");
-
- if (rc_dev->current & SANYO)
- fprintf(fp, "+sanyo\n");
-
- if (rc_dev->current & LIRC)
- fprintf(fp, "+lirc\n");
-
- if (rc_dev->current & RC_5_SZ)
- fprintf(fp, "+rc-5-sz\n");
-
- if (rc_dev->current & SHARP)
- fprintf(fp, "+sharp\n");
-
- if (rc_dev->current & MCE_KBD)
- fprintf(fp, "+mce-kbd\n");
-
- if (rc_dev->current & XMP)
- fprintf(fp, "+xmp\n");
-
- if (rc_dev->current & OTHER)
- fprintf(fp, "+unknown\n");
+ write_sysfs_protocols(rc_dev->current, fp, "+%s\n");
if (fclose(fp)) {
perror(name);
@@ -1064,34 +988,6 @@ static int v2_set_protocols(struct rc_device *rc_dev)
return 0;
}
-static void show_proto( enum ir_protocols proto)
-{
- if (proto & NEC)
- fprintf (stderr, "NEC ");
- if (proto & RC_5)
- fprintf (stderr, "RC-5 ");
- if (proto & RC_6)
- fprintf (stderr, "RC-6 ");
- if (proto & JVC)
- fprintf (stderr, "JVC ");
- if (proto & SONY)
- fprintf (stderr, "SONY ");
- if (proto & SANYO)
- fprintf (stderr, "SANYO ");
- if (proto & LIRC)
- fprintf (stderr, "LIRC ");
- if (proto & RC_5_SZ)
- fprintf (stderr, "RC-5-SZ ");
- if (proto & SHARP)
- fprintf (stderr, "SHARP ");
- if (proto & MCE_KBD)
- fprintf (stderr, "MCE_KBD ");
- if (proto & XMP)
- fprintf (stderr, "XMP ");
- if (proto & OTHER)
- fprintf (stderr, _("other "));
-}
-
static int get_attribs(struct rc_device *rc_dev, char *sysfs_name)
{
struct uevents *uevent;
@@ -1189,29 +1085,29 @@ static int get_attribs(struct rc_device *rc_dev, char *sysfs_name)
rc_dev->version = VERSION_1;
rc_dev->supported = v1_get_hw_protocols(cur->name);
} else if (strstr(cur->name, "/nec_decoder")) {
- rc_dev->supported |= NEC;
+ rc_dev->supported |= SYSFS_NEC;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= NEC;
+ rc_dev->current |= SYSFS_NEC;
} else if (strstr(cur->name, "/rc5_decoder")) {
- rc_dev->supported |= RC_5;
+ rc_dev->supported |= SYSFS_RC5;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= RC_5;
+ rc_dev->current |= SYSFS_RC5;
} else if (strstr(cur->name, "/rc6_decoder")) {
- rc_dev->supported |= RC_6;
+ rc_dev->supported |= SYSFS_RC6;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= RC_6;
+ rc_dev->current |= SYSFS_RC6;
} else if (strstr(cur->name, "/jvc_decoder")) {
- rc_dev->supported |= JVC;
+ rc_dev->supported |= SYSFS_JVC;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= JVC;
+ rc_dev->current |= SYSFS_JVC;
} else if (strstr(cur->name, "/sony_decoder")) {
- rc_dev->supported |= SONY;
+ rc_dev->supported |= SYSFS_SONY;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SONY;
+ rc_dev->current |= SYSFS_SONY;
} else if (strstr(cur->name, "/xmp_decoder")) {
- rc_dev->supported |= XMP;
+ rc_dev->supported |= SYSFS_XMP;
if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= XMP;
+ rc_dev->current |= SYSFS_XMP;
}
}
@@ -1234,24 +1130,24 @@ static int set_proto(struct rc_device *rc_dev)
}
if (rc_dev->type == SOFTWARE_DECODER) {
- if (rc_dev->supported & NEC)
+ if (rc_dev->supported & SYSFS_NEC)
rc += v1_set_sw_enabled_protocol(rc_dev, "/nec_decoder",
- rc_dev->current & NEC);
- if (rc_dev->supported & RC_5)
+ rc_dev->current & SYSFS_NEC);
+ if (rc_dev->supported & SYSFS_RC5)
rc += v1_set_sw_enabled_protocol(rc_dev, "/rc5_decoder",
- rc_dev->current & RC_5);
- if (rc_dev->supported & RC_6)
+ rc_dev->current & SYSFS_RC5);
+ if (rc_dev->supported & SYSFS_RC6)
rc += v1_set_sw_enabled_protocol(rc_dev, "/rc6_decoder",
- rc_dev->current & RC_6);
- if (rc_dev->supported & JVC)
+ rc_dev->current & SYSFS_RC6);
+ if (rc_dev->supported & SYSFS_JVC)
rc += v1_set_sw_enabled_protocol(rc_dev, "/jvc_decoder",
- rc_dev->current & JVC);
- if (rc_dev->supported & SONY)
+ rc_dev->current & SYSFS_JVC);
+ if (rc_dev->supported & SYSFS_SONY)
rc += v1_set_sw_enabled_protocol(rc_dev, "/sony_decoder",
- rc_dev->current & SONY);
- if (rc_dev->supported & XMP)
+ rc_dev->current & SYSFS_SONY);
+ if (rc_dev->supported & SYSFS_XMP)
rc += v1_set_sw_enabled_protocol(rc_dev, "/xmp_decoder",
- rc_dev->current & XMP);
+ rc_dev->current & SYSFS_XMP);
} else {
rc = v1_set_hw_protocols(rc_dev);
}
@@ -1338,7 +1234,7 @@ static void display_proto(struct rc_device *rc_dev)
fprintf(stderr, _("Current protocols: "));
else
fprintf(stderr, _("Enabled protocols: "));
- show_proto(rc_dev->current);
+ write_sysfs_protocols(rc_dev->current, stderr, "%s ");
fprintf(stderr, "\n");
}
@@ -1548,7 +1444,7 @@ static int show_sysfs_attribs(struct rc_device *rc_dev)
rc_dev->drv_name,
rc_dev->keytable_name);
fprintf(stderr, _("\tSupported protocols: "));
- show_proto(rc_dev->supported);
+ write_sysfs_protocols(rc_dev->supported, stderr, "%s ");
fprintf(stderr, "\n\t");
display_proto(rc_dev);
fd = open(rc_dev->input_name, O_RDONLY);
@@ -1706,7 +1602,7 @@ int main(int argc, char *argv[])
fprintf(stderr, _("Couldn't change the IR protocols\n"));
else {
fprintf(stderr, _("Protocols changed to "));
- show_proto(rc_dev.current);
+ write_sysfs_protocols(rc_dev.current, stderr, "%s ");
fprintf(stderr, "\n");
}
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] ir-keytable: replace more sysfs if-else code with loops
2015-04-06 11:25 [PATCH 0/4] Add protocol support to ir-keytable David Härdeman
2015-04-06 11:26 ` [PATCH 1/4] ir-keytable: clarify the meaning of ir protocols David Härdeman
@ 2015-04-06 11:26 ` David Härdeman
2015-04-06 11:26 ` [PATCH 3/4] ir-keytable: cleanup keytable code David Härdeman
2015-04-06 11:26 ` [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings David Härdeman
3 siblings, 0 replies; 7+ messages in thread
From: David Härdeman @ 2015-04-06 11:26 UTC (permalink / raw)
To: linux-media; +Cc: m.chehab
Document the sysfs1 interface in protocol_map[] and replace some
more if-else code with loops.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
utils/keytable/keytable.c | 124 ++++++++++++++++++++-------------------------
1 file changed, 55 insertions(+), 69 deletions(-)
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 2ca693f..949eed9 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -109,36 +109,37 @@ enum sysfs_protocols {
struct protocol_map_entry {
const char *name;
+ const char *sysfs1_name;
enum sysfs_protocols sysfs_protocol;
};
const struct protocol_map_entry protocol_map[] = {
- { "unknown", SYSFS_UNKNOWN },
- { "other", SYSFS_OTHER },
- { "lirc", SYSFS_LIRC },
- { "rc-5", SYSFS_RC5 },
- { "rc5", SYSFS_RC5 },
- { "rc-5x", SYSFS_INVALID },
- { "rc5x", SYSFS_INVALID },
- { "jvc", SYSFS_JVC },
- { "sony", SYSFS_SONY },
- { "sony12", SYSFS_INVALID },
- { "sony15", SYSFS_INVALID },
- { "sony20", SYSFS_INVALID },
- { "nec", SYSFS_NEC },
- { "sanyo", SYSFS_SANYO },
- { "mce-kbd", SYSFS_MCE_KBD },
- { "mce_kbd", SYSFS_MCE_KBD },
- { "rc-6", SYSFS_RC6 },
- { "rc6", SYSFS_RC6 },
- { "rc-6-0", SYSFS_INVALID },
- { "rc-6-6a-20", SYSFS_INVALID },
- { "rc-6-6a-24", SYSFS_INVALID },
- { "rc-6-6a-32", SYSFS_INVALID },
- { "rc-6-mce", SYSFS_INVALID },
- { "sharp", SYSFS_SHARP },
- { "xmp", SYSFS_XMP },
- { NULL, SYSFS_INVALID },
+ { "unknown", NULL, SYSFS_UNKNOWN },
+ { "other", NULL, SYSFS_OTHER },
+ { "lirc", NULL, SYSFS_LIRC },
+ { "rc-5", "/rc5_decoder", SYSFS_RC5 },
+ { "rc5", NULL, SYSFS_RC5 },
+ { "rc-5x", NULL, SYSFS_INVALID },
+ { "rc5x", NULL, SYSFS_INVALID },
+ { "jvc", "/jvc_decoder", SYSFS_JVC },
+ { "sony", "/sony_decoder",SYSFS_SONY },
+ { "sony12", NULL, SYSFS_INVALID },
+ { "sony15", NULL, SYSFS_INVALID },
+ { "sony20", NULL, SYSFS_INVALID },
+ { "nec", "/nec_decoder", SYSFS_NEC },
+ { "sanyo", NULL, SYSFS_SANYO },
+ { "mce-kbd", NULL, SYSFS_MCE_KBD },
+ { "mce_kbd", NULL, SYSFS_MCE_KBD },
+ { "rc-6", "/rc6_decoder", SYSFS_RC6 },
+ { "rc6", NULL, SYSFS_RC6 },
+ { "rc-6-0", NULL, SYSFS_INVALID },
+ { "rc-6-6a-20", NULL, SYSFS_INVALID },
+ { "rc-6-6a-24", NULL, SYSFS_INVALID },
+ { "rc-6-6a-32", NULL, SYSFS_INVALID },
+ { "rc-6-mce", NULL, SYSFS_INVALID },
+ { "sharp", NULL, SYSFS_SHARP },
+ { "xmp", "/xmp_decoder", SYSFS_XMP },
+ { NULL, NULL, SYSFS_INVALID },
};
static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allowed)
@@ -886,7 +887,7 @@ static int v1_get_sw_enabled_protocol(char *dirname)
}
static int v1_set_sw_enabled_protocol(struct rc_device *rc_dev,
- char *dirname, int enabled)
+ const char *dirname, int enabled)
{
FILE *fp;
char name[512];
@@ -1084,30 +1085,20 @@ static int get_attribs(struct rc_device *rc_dev, char *sysfs_name)
} else if (strstr(cur->name, "/supported_protocols")) {
rc_dev->version = VERSION_1;
rc_dev->supported = v1_get_hw_protocols(cur->name);
- } else if (strstr(cur->name, "/nec_decoder")) {
- rc_dev->supported |= SYSFS_NEC;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_NEC;
- } else if (strstr(cur->name, "/rc5_decoder")) {
- rc_dev->supported |= SYSFS_RC5;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_RC5;
- } else if (strstr(cur->name, "/rc6_decoder")) {
- rc_dev->supported |= SYSFS_RC6;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_RC6;
- } else if (strstr(cur->name, "/jvc_decoder")) {
- rc_dev->supported |= SYSFS_JVC;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_JVC;
- } else if (strstr(cur->name, "/sony_decoder")) {
- rc_dev->supported |= SYSFS_SONY;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_SONY;
- } else if (strstr(cur->name, "/xmp_decoder")) {
- rc_dev->supported |= SYSFS_XMP;
- if (v1_get_sw_enabled_protocol(cur->name))
- rc_dev->current |= SYSFS_XMP;
+ } else {
+ const struct protocol_map_entry *pme;
+
+ for (pme = protocol_map; pme->name; pme++) {
+ if (!pme->sysfs1_name)
+ continue;
+
+ if (strstr(cur->name, pme->sysfs1_name)) {
+ rc_dev->supported |= pme->sysfs_protocol;
+ if (v1_get_sw_enabled_protocol(cur->name))
+ rc_dev->supported |= pme->sysfs_protocol;
+ break;
+ }
+ }
}
}
@@ -1130,24 +1121,19 @@ static int set_proto(struct rc_device *rc_dev)
}
if (rc_dev->type == SOFTWARE_DECODER) {
- if (rc_dev->supported & SYSFS_NEC)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/nec_decoder",
- rc_dev->current & SYSFS_NEC);
- if (rc_dev->supported & SYSFS_RC5)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/rc5_decoder",
- rc_dev->current & SYSFS_RC5);
- if (rc_dev->supported & SYSFS_RC6)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/rc6_decoder",
- rc_dev->current & SYSFS_RC6);
- if (rc_dev->supported & SYSFS_JVC)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/jvc_decoder",
- rc_dev->current & SYSFS_JVC);
- if (rc_dev->supported & SYSFS_SONY)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/sony_decoder",
- rc_dev->current & SYSFS_SONY);
- if (rc_dev->supported & SYSFS_XMP)
- rc += v1_set_sw_enabled_protocol(rc_dev, "/xmp_decoder",
- rc_dev->current & SYSFS_XMP);
+ const struct protocol_map_entry *pme;
+
+ for (pme = protocol_map; pme->name; pme++) {
+ if (!pme->sysfs1_name)
+ continue;
+
+ if (!(rc_dev->supported & pme->sysfs_protocol))
+ continue;
+
+ rc += v1_set_sw_enabled_protocol(rc_dev, pme->sysfs1_name,
+ rc_dev->current & pme->sysfs_protocol);
+ }
+
} else {
rc = v1_set_hw_protocols(rc_dev);
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] ir-keytable: cleanup keytable code
2015-04-06 11:25 [PATCH 0/4] Add protocol support to ir-keytable David Härdeman
2015-04-06 11:26 ` [PATCH 1/4] ir-keytable: clarify the meaning of ir protocols David Härdeman
2015-04-06 11:26 ` [PATCH 2/4] ir-keytable: replace more sysfs if-else code with loops David Härdeman
@ 2015-04-06 11:26 ` David Härdeman
2015-04-06 11:26 ` [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings David Härdeman
3 siblings, 0 replies; 7+ messages in thread
From: David Härdeman @ 2015-04-06 11:26 UTC (permalink / raw)
To: linux-media; +Cc: m.chehab
Cleanup the keytable code by giving the struct members more explicit
names (scancode instead of codes[0], keycode instead of codes[1]).
Also, replace a linked list implementation using a quirky empty list
member as the head of the list rather than the classical pointer.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
utils/keytable/keytable.c | 100 ++++++++++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 43 deletions(-)
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 949eed9..63eea2e 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -55,12 +55,14 @@ struct input_keymap_entry_v2 {
#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry_v2)
#endif
-struct keytable {
- u_int32_t codes[2];
- struct input_keymap_entry_v2 keymap;
- struct keytable *next;
+struct keytable_entry {
+ u_int32_t scancode;
+ u_int32_t keycode;
+ struct keytable_entry *next;
};
+struct keytable_entry *keytable = NULL;
+
struct uevents {
char *key;
char *value;
@@ -237,12 +239,6 @@ static int delay = 0;
static int period = 0;
static enum sysfs_protocols ch_proto = 0;
-struct keytable keys = {
- .codes = {0, 0},
- .next = NULL
-};
-
-
struct cfgfile cfg = {
NULL, NULL, NULL, NULL
};
@@ -268,13 +264,12 @@ struct rc_device {
enum sysfs_protocols supported, current; /* Current and supported IR protocols */
};
-struct keytable *nextkey = &keys;
-
static error_t parse_keyfile(char *fname, char **table)
{
FILE *fin;
int value, line = 0;
char *scancode, *keycode, s[2048];
+ struct keytable_entry *ke;
*table = NULL;
@@ -356,14 +351,16 @@ static error_t parse_keyfile(char *fname, char **table)
perror(_("value"));
}
- nextkey->codes[0] = (unsigned) strtoul(scancode, NULL, 0);
- nextkey->codes[1] = (unsigned) value;
- nextkey->next = calloc(1, sizeof(*nextkey));
- if (!nextkey->next) {
+ ke = calloc(1, sizeof(*ke));
+ if (!ke) {
perror("parse_keyfile");
return ENOMEM;
}
- nextkey = nextkey->next;
+
+ ke->scancode = strtoul(scancode, NULL, 0);
+ ke->keycode = value;
+ ke->next = keytable;
+ keytable = ke;
}
fclose(fin);
@@ -497,33 +494,46 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
case 'k':
p = strtok(arg, ":=");
do {
+ struct keytable_entry *ke;
+
if (!p)
goto err_inval;
- nextkey->codes[0] = strtoul(p, NULL, 0);
- if (errno)
+
+ ke = calloc(1, sizeof(*ke));
+ if (!ke) {
+ perror(_("No memory!\n"));
+ return ENOMEM;
+ }
+
+ ke->scancode = strtoul(p, NULL, 0);
+ if (errno) {
+ free(ke);
goto err_inval;
+ }
p = strtok(NULL, ",;");
- if (!p)
+ if (!p) {
+ free(ke);
goto err_inval;
+ }
+
key = parse_code(p);
if (key == -1) {
key = strtol(p, NULL, 0);
- if (errno)
+ if (errno) {
+ free(ke);
goto err_inval;
+ }
}
- nextkey->codes[1] = key;
+
+ ke->keycode = key;
if (debug)
fprintf(stderr, _("scancode 0x%04x=%u\n"),
- nextkey->codes[0], nextkey->codes[1]);
+ ke->scancode, ke->keycode);
- nextkey->next = calloc(1, sizeof(keys));
- if (!nextkey->next) {
- perror(_("No memory!\n"));
- return ENOMEM;
- }
- nextkey = nextkey->next;
+ ke->next = keytable;
+ keytable = ke;
p = strtok(NULL, ":=");
} while (p);
@@ -1189,26 +1199,30 @@ static void clear_table(int fd)
static int add_keys(int fd)
{
int write_cnt = 0;
+ struct keytable_entry *ke;
+ unsigned codes[2];
- nextkey = &keys;
- while (nextkey->next) {
- struct keytable *old;
-
+ for (ke = keytable; ke; ke = ke->next) {
write_cnt++;
if (debug)
fprintf(stderr, "\t%04x=%04x\n",
- nextkey->codes[0], nextkey->codes[1]);
+ ke->scancode, ke->keycode);
- if (ioctl(fd, EVIOCSKEYCODE, nextkey->codes)) {
+ codes[0] = ke->scancode;
+ codes[1] = ke->keycode;
+
+ if (ioctl(fd, EVIOCSKEYCODE, codes)) {
fprintf(stderr,
_("Setting scancode 0x%04x with 0x%04x via "),
- nextkey->codes[0], nextkey->codes[1]);
+ ke->scancode, ke->keycode);
perror("EVIOCSKEYCODE");
}
- old = nextkey;
- nextkey = nextkey->next;
- if (old != &keys)
- free(old);
+ }
+
+ while (keytable) {
+ ke = keytable;
+ keytable = ke->next;
+ free(ke);
}
return write_cnt;
@@ -1460,7 +1474,7 @@ int main(int argc, char *argv[])
argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0);
/* Just list all devices */
- if (!clear && !readtable && !keys.next && !ch_proto && !cfg.next && !test && !delay && !period) {
+ if (!clear && !readtable && !keytable && !ch_proto && !cfg.next && !test && !delay && !period) {
if (devicename) {
fd = open(devicename, O_RDONLY);
if (fd < 0) {
@@ -1477,7 +1491,7 @@ int main(int argc, char *argv[])
return 0;
}
- if (cfg.next && (clear || keys.next || ch_proto || devicename)) {
+ if (cfg.next && (clear || keytable || ch_proto || devicename)) {
fprintf (stderr, _("Auto-mode can be used only with --read, --debug and --sysdev options\n"));
return -1;
}
@@ -1545,7 +1559,7 @@ int main(int argc, char *argv[])
return -1;
}
}
- if (!keys.next) {
+ if (!keytable) {
fprintf(stderr, _("Empty table %s\n"), fname);
return -1;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings
2015-04-06 11:25 [PATCH 0/4] Add protocol support to ir-keytable David Härdeman
` (2 preceding siblings ...)
2015-04-06 11:26 ` [PATCH 3/4] ir-keytable: cleanup keytable code David Härdeman
@ 2015-04-06 11:26 ` David Härdeman
2015-05-14 21:24 ` Mauro Carvalho Chehab
3 siblings, 1 reply; 7+ messages in thread
From: David Härdeman @ 2015-04-06 11:26 UTC (permalink / raw)
To: linux-media; +Cc: m.chehab
Introduce a list of "kernel" ir protocols (e.g. "sony12" instead of "sony")
and extend the set-key command to ir-keytable to allow for a mapping of the
form "protocol:scancode=keycode" in addition to the old "scancode=keycode"
format. The code automatically falls back to the old behaviour if the
kernel doesn't support the new approach with protocols.
The read command is also updated to show the protocol information if the
kernel supports it.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
utils/keytable/keytable.c | 288 ++++++++++++++++++++++++++++++++-------------
1 file changed, 202 insertions(+), 86 deletions(-)
diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 63eea2e..fd50095 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -55,13 +55,22 @@ struct input_keymap_entry_v2 {
#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry_v2)
#endif
-struct keytable_entry {
- u_int32_t scancode;
- u_int32_t keycode;
- struct keytable_entry *next;
+struct rc_scancode {
+ u_int16_t protocol;
+ u_int16_t reserved[3];
+ u_int64_t scancode;
};
-struct keytable_entry *keytable = NULL;
+struct rc_keymap_entry {
+ u_int8_t flags;
+ u_int8_t len;
+ u_int16_t index;
+ u_int32_t keycode;
+ union {
+ struct rc_scancode rc;
+ u_int8_t raw[32];
+ };
+};
struct uevents {
char *key;
@@ -109,41 +118,76 @@ enum sysfs_protocols {
SYSFS_INVALID = 0,
};
+enum kernel_protocol {
+ KERN_UNKNOWN = 0, /* Protocol not known */
+ KERN_OTHER = 1, /* Protocol known but proprietary */
+ KERN_LIRC = 2, /* Pass raw IR to lirc userspace */
+ KERN_RC5 = 3, /* Philips RC5 protocol */
+ KERN_RC5X = 4, /* Philips RC5x protocol */
+ KERN_RC5_SZ = 5, /* StreamZap variant of RC5 */
+ KERN_JVC = 6, /* JVC protocol */
+ KERN_SONY12 = 7, /* Sony 12 bit protocol */
+ KERN_SONY15 = 8, /* Sony 15 bit protocol */
+ KERN_SONY20 = 9, /* Sony 20 bit protocol */
+ KERN_NEC = 10, /* NEC protocol */
+ KERN_SANYO = 11, /* Sanyo protocol */
+ KERN_MCE_KBD = 12, /* RC6-ish MCE keyboard/mouse */
+ KERN_RC6_0 = 13, /* Philips RC6-0-16 protocol */
+ KERN_RC6_6A_20 = 14, /* Philips RC6-6A-20 protocol */
+ KERN_RC6_6A_24 = 15, /* Philips RC6-6A-24 protocol */
+ KERN_RC6_6A_32 = 16, /* Philips RC6-6A-32 protocol */
+ KERN_RC6_MCE = 17, /* MCE (Philips RC6-6A-32 subtype) protocol */
+ KERN_SHARP = 18, /* Sharp protocol */
+ KERN_XMP = 19, /* XMP protocol */
+ KERN_INVALID = 31, /* internal, no real protocol number */
+};
+
struct protocol_map_entry {
const char *name;
const char *sysfs1_name;
enum sysfs_protocols sysfs_protocol;
+ enum kernel_protocol kernel_protocol;
};
const struct protocol_map_entry protocol_map[] = {
- { "unknown", NULL, SYSFS_UNKNOWN },
- { "other", NULL, SYSFS_OTHER },
- { "lirc", NULL, SYSFS_LIRC },
- { "rc-5", "/rc5_decoder", SYSFS_RC5 },
- { "rc5", NULL, SYSFS_RC5 },
- { "rc-5x", NULL, SYSFS_INVALID },
- { "rc5x", NULL, SYSFS_INVALID },
- { "jvc", "/jvc_decoder", SYSFS_JVC },
- { "sony", "/sony_decoder",SYSFS_SONY },
- { "sony12", NULL, SYSFS_INVALID },
- { "sony15", NULL, SYSFS_INVALID },
- { "sony20", NULL, SYSFS_INVALID },
- { "nec", "/nec_decoder", SYSFS_NEC },
- { "sanyo", NULL, SYSFS_SANYO },
- { "mce-kbd", NULL, SYSFS_MCE_KBD },
- { "mce_kbd", NULL, SYSFS_MCE_KBD },
- { "rc-6", "/rc6_decoder", SYSFS_RC6 },
- { "rc6", NULL, SYSFS_RC6 },
- { "rc-6-0", NULL, SYSFS_INVALID },
- { "rc-6-6a-20", NULL, SYSFS_INVALID },
- { "rc-6-6a-24", NULL, SYSFS_INVALID },
- { "rc-6-6a-32", NULL, SYSFS_INVALID },
- { "rc-6-mce", NULL, SYSFS_INVALID },
- { "sharp", NULL, SYSFS_SHARP },
- { "xmp", "/xmp_decoder", SYSFS_XMP },
- { NULL, NULL, SYSFS_INVALID },
+ { "unknown", NULL, SYSFS_UNKNOWN, KERN_UNKNOWN },
+ { "other", NULL, SYSFS_OTHER, KERN_OTHER },
+ { "lirc", NULL, SYSFS_LIRC, KERN_LIRC },
+ { "rc-5", "/rc5_decoder", SYSFS_RC5, KERN_RC5 },
+ { "rc5", NULL, SYSFS_RC5, KERN_RC5 },
+ { "rc-5x", NULL, SYSFS_INVALID, KERN_RC5X },
+ { "rc5x", NULL, SYSFS_INVALID, KERN_RC5X },
+ { "jvc", "/jvc_decoder", SYSFS_JVC, KERN_JVC },
+ { "sony", "/sony_decoder",SYSFS_SONY, KERN_INVALID },
+ { "sony12", NULL, SYSFS_INVALID, KERN_SONY12 },
+ { "sony15", NULL, SYSFS_INVALID, KERN_SONY15 },
+ { "sony20", NULL, SYSFS_INVALID, KERN_SONY20 },
+ { "nec", "/nec_decoder", SYSFS_NEC, KERN_NEC },
+ { "sanyo", NULL, SYSFS_SANYO, KERN_SANYO },
+ { "mce-kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
+ { "mce_kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
+ { "rc-6", "/rc6_decoder", SYSFS_RC6, KERN_INVALID },
+ { "rc6", NULL, SYSFS_RC6, KERN_INVALID },
+ { "rc-6-0", NULL, SYSFS_INVALID, KERN_RC6_0 },
+ { "rc-6-6a-20", NULL, SYSFS_INVALID, KERN_RC6_6A_20 },
+ { "rc-6-6a-24", NULL, SYSFS_INVALID, KERN_RC6_6A_24 },
+ { "rc-6-6a-32", NULL, SYSFS_INVALID, KERN_RC6_6A_32 },
+ { "rc-6-mce", NULL, SYSFS_INVALID, KERN_RC6_MCE },
+ { "sharp", NULL, SYSFS_SHARP, KERN_SHARP },
+ { "xmp", "/xmp_decoder", SYSFS_XMP, KERN_XMP },
+ { NULL, NULL, SYSFS_INVALID, KERN_INVALID },
+};
+
+struct keytable_entry {
+ u_int32_t scancode;
+ u_int32_t keycode;
+ enum kernel_protocol protocol;
+ struct keytable_entry *next;
};
+struct keytable_entry *keytable = NULL;
+
+
static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allowed)
{
const struct protocol_map_entry *pme;
@@ -162,6 +206,21 @@ static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allo
return SYSFS_INVALID;
}
+static enum kernel_protocol parse_kernel_protocol(const char *name)
+{
+ const struct protocol_map_entry *pme;
+
+ if (!name)
+ return KERN_INVALID;
+
+ for (pme = protocol_map; pme->name; pme++) {
+ if (!strcasecmp(name, pme->name))
+ return pme->kernel_protocol;
+ }
+
+ return KERN_INVALID;
+}
+
static void write_sysfs_protocols(enum sysfs_protocols protocols, FILE *fp, const char *fmt)
{
const struct protocol_map_entry *pme;
@@ -197,6 +256,7 @@ static const char doc[] = N_(
" SYSDEV - the ir class as found at /sys/class/rc\n"
" TABLE - a file with a set of scancode=keycode value pairs\n"
" SCANKEY - a set of scancode1=keycode1,scancode2=keycode2.. value pairs\n"
+ " or (experimentally) a list of protocol1:scancode1=keycode1,protocol2:scancode2=keycode2...triplets\n"
" PROTOCOL - protocol name (nec, rc-5, rc-6, jvc, sony, sanyo, rc-5-sz, lirc,\n"
" sharp, mce_kbd, xmp, other, all) to be enabled\n"
" DELAY - Delay before repeating a keystroke\n"
@@ -447,7 +507,6 @@ err_einval:
static error_t parse_opt(int k, char *arg, struct argp_state *state)
{
char *p;
- long key;
int rc;
switch (k) {
@@ -492,51 +551,69 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
break;
}
case 'k':
- p = strtok(arg, ":=");
- do {
+ for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
+ char *protocol_str;
+ enum kernel_protocol protocol = KERN_INVALID;
+ long long int scancode;
+ char *keycode_str;
+ long keycode;
struct keytable_entry *ke;
- if (!p)
- goto err_inval;
-
- ke = calloc(1, sizeof(*ke));
- if (!ke) {
- perror(_("No memory!\n"));
- return ENOMEM;
+ errno = 0;
+ /* New format - protocol:scancode=keycode */
+ if (sscanf(p, " %m[^:] : %lli = %ms", &protocol_str, &scancode, &keycode_str) != 3) {
+ if (errno != 0) {
+ fprintf(stderr, _("sscanf failed!\n"));
+ return errno;
+ }
+
+ /* Old format - scancode=keycode */
+ protocol_str = NULL;
+ if (sscanf(p, " %lli = %ms", &scancode, &keycode_str) != 2) {
+ if (errno != 0) {
+ fprintf(stderr, _("sscanf failed!\n"));
+ return errno;
+ }
+ goto err_inval;
+ }
}
- ke->scancode = strtoul(p, NULL, 0);
- if (errno) {
- free(ke);
- goto err_inval;
+ keycode = parse_code(keycode_str);
+ if (keycode == -1) {
+ errno = 0;
+ keycode = strtoul(keycode_str, NULL, 0);
+ if (errno)
+ keycode = -1;
}
+ free(keycode_str);
- p = strtok(NULL, ",;");
- if (!p) {
- free(ke);
- goto err_inval;
- }
+ if (protocol_str) {
+ protocol = parse_kernel_protocol(protocol_str);
+ free(protocol_str);
- key = parse_code(p);
- if (key == -1) {
- key = strtol(p, NULL, 0);
- if (errno) {
- free(ke);
+ if (protocol == KERN_INVALID)
goto err_inval;
- }
}
- ke->keycode = key;
+ if (keycode == -1 || scancode < 0)
+ goto err_inval;
- if (debug)
- fprintf(stderr, _("scancode 0x%04x=%u\n"),
- ke->scancode, ke->keycode);
+ ke = calloc(1, sizeof(*ke));
+ if (!ke) {
+ perror(_("No memory!\n"));
+ return ENOMEM;
+ }
+ ke->scancode = scancode;
+ ke->keycode = keycode;
+ ke->protocol = protocol;
ke->next = keytable;
keytable = ke;
- p = strtok(NULL, ":=");
- } while (p);
+ if (debug)
+ fprintf(stderr, _("scancode %i:0x%04x=%u\n"),
+ ke->protocol, ke->scancode, ke->keycode);
+ }
break;
case 'p':
for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
@@ -579,21 +656,24 @@ static struct argp argp = {
.doc = doc,
};
-static void prtcode(int *codes)
+static void print_mapping(enum kernel_protocol protocol, unsigned scancode, unsigned keycode)
{
struct parse_event *p;
+ if (protocol != KERN_INVALID)
+ printf(_("protocol 0x%04x, "), protocol);
+
for (p = key_events; p->name != NULL; p++) {
- if (p->value == (unsigned)codes[1]) {
- printf(_("scancode 0x%04x = %s (0x%02x)\n"), codes[0], p->name, codes[1]);
+ if (p->value == keycode) {
+ printf(_("scancode 0x%04x = %s (0x%02x)\n"), scancode, p->name, keycode);
return;
}
}
- if (isprint (codes[1]))
- printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), codes[0], codes[1], codes[1]);
+ if (isprint(keycode))
+ printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), scancode, keycode, keycode);
else
- printf(_("scancode 0x%04x = 0x%02x\n"), codes[0], codes[1]);
+ printf(_("scancode 0x%04x = 0x%02x\n"), scancode, keycode);
}
static void free_names(struct sysfs_names *names)
@@ -1201,12 +1281,30 @@ static int add_keys(int fd)
int write_cnt = 0;
struct keytable_entry *ke;
unsigned codes[2];
+ struct rc_keymap_entry rke;
for (ke = keytable; ke; ke = ke->next) {
write_cnt++;
if (debug)
- fprintf(stderr, "\t%04x=%04x\n",
- ke->scancode, ke->keycode);
+ fprintf(stderr, "\t%u:%04x=%04x\n",
+ ke->protocol, ke->scancode, ke->keycode);
+
+ if (ke->protocol != KERN_INVALID) {
+ memset(&rke, '\0', sizeof(rke));
+ rke.len = sizeof(rke.rc);
+ rke.keycode = ke->keycode;
+ rke.rc.protocol = ke->protocol;
+ rke.rc.scancode = ke->scancode;
+
+ if (debug)
+ fprintf(stderr, _("Attempting new EVIOCSKEYCODE_V2 ioctl\n"));
+
+ if (ioctl(fd, EVIOCSKEYCODE_V2, &rke) == 0)
+ continue;
+
+ if (debug)
+ fprintf(stderr, _("New EVIOCSKEYCODE_V2 ioctl failed\n"));
+ }
codes[0] = ke->scancode;
codes[1] = ke->keycode;
@@ -1329,7 +1427,7 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
if (ioctl(fd, EVIOCGKEYCODE, codes) == -1)
perror("EVIOCGKEYCODE");
else if (codes[1] != KEY_RESERVED)
- prtcode(codes);
+ print_mapping(KERN_INVALID, codes[0], codes[1]);
}
}
display_proto(rc_dev);
@@ -1337,27 +1435,45 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
static void display_table_v2(struct rc_device *rc_dev, int fd)
{
+ struct input_keymap_entry_v2 ike;
+ struct rc_keymap_entry rke;
+ bool first = true, rke_supported = true;
+ u_int32_t scancode;
int i;
- struct input_keymap_entry_v2 entry;
- int codes[2];
- memset(&entry, '\0', sizeof(entry));
- i = 0;
- do {
- entry.flags = KEYMAP_BY_INDEX;
- entry.index = i;
- entry.len = sizeof(u_int32_t);
+ for (i = 0; ; i++) {
+ if (first || rke_supported) {
+ memset(&rke, '\0', sizeof(rke));
+ rke.flags = KEYMAP_BY_INDEX;
+ rke.index = i;
+ rke.len = sizeof(rke.rc);
- if (ioctl(fd, EVIOCGKEYCODE_V2, &entry) == -1)
+ if (ioctl(fd, EVIOCGKEYCODE_V2, &rke) == -1) {
+ if (first)
+ rke_supported = false;
+ else
+ break;
+ }
+
+ first = false;
+ if (rke_supported) {
+ print_mapping(rke.rc.protocol, rke.rc.scancode, rke.keycode);
+ continue;
+ }
+ }
+
+ memset(&ike, '\0', sizeof(ike));
+ ike.flags = KEYMAP_BY_INDEX;
+ ike.index = i;
+ ike.len = sizeof(scancode);
+
+ if (ioctl(fd, EVIOCGKEYCODE_V2, &ike) == -1)
break;
/* FIXME: Extend it to support scancodes > 32 bits */
- memcpy(&codes[0], entry.scancode, sizeof(codes[0]));
- codes[1] = entry.keycode;
-
- prtcode(codes);
- i++;
- } while (1);
+ memcpy(&scancode, ike.scancode, sizeof(scancode));
+ print_mapping(KERN_INVALID, scancode, ike.keycode);
+ }
display_proto(rc_dev);
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings
2015-04-06 11:26 ` [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings David Härdeman
@ 2015-05-14 21:24 ` Mauro Carvalho Chehab
2015-05-19 21:36 ` David Härdeman
0 siblings, 1 reply; 7+ messages in thread
From: Mauro Carvalho Chehab @ 2015-05-14 21:24 UTC (permalink / raw)
To: David Härdeman; +Cc: linux-media
Em Mon, 06 Apr 2015 13:26:18 +0200
David Härdeman <david@hardeman.nu> escreveu:
> Introduce a list of "kernel" ir protocols (e.g. "sony12" instead of "sony")
> and extend the set-key command to ir-keytable to allow for a mapping of the
> form "protocol:scancode=keycode" in addition to the old "scancode=keycode"
> format. The code automatically falls back to the old behaviour if the
> kernel doesn't support the new approach with protocols.
>
> The read command is also updated to show the protocol information if the
> kernel supports it.
I applied patches 1 to 3 of this series, as they are not based on any
new feature.
This patch, however, needs to wait for the Kernel patch to be acked, and
may be modified, depending on the review process.
I'll mark it at patchwork as RFC. Please re-submit after we merge the
Kernel changes.
Thanks,
Mauro
>
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
> utils/keytable/keytable.c | 288 ++++++++++++++++++++++++++++++++-------------
> 1 file changed, 202 insertions(+), 86 deletions(-)
>
> diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
> index 63eea2e..fd50095 100644
> --- a/utils/keytable/keytable.c
> +++ b/utils/keytable/keytable.c
> @@ -55,13 +55,22 @@ struct input_keymap_entry_v2 {
> #define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry_v2)
> #endif
>
> -struct keytable_entry {
> - u_int32_t scancode;
> - u_int32_t keycode;
> - struct keytable_entry *next;
> +struct rc_scancode {
> + u_int16_t protocol;
> + u_int16_t reserved[3];
> + u_int64_t scancode;
> };
>
> -struct keytable_entry *keytable = NULL;
> +struct rc_keymap_entry {
> + u_int8_t flags;
> + u_int8_t len;
> + u_int16_t index;
> + u_int32_t keycode;
> + union {
> + struct rc_scancode rc;
> + u_int8_t raw[32];
> + };
> +};
>
> struct uevents {
> char *key;
> @@ -109,41 +118,76 @@ enum sysfs_protocols {
> SYSFS_INVALID = 0,
> };
>
> +enum kernel_protocol {
> + KERN_UNKNOWN = 0, /* Protocol not known */
> + KERN_OTHER = 1, /* Protocol known but proprietary */
> + KERN_LIRC = 2, /* Pass raw IR to lirc userspace */
> + KERN_RC5 = 3, /* Philips RC5 protocol */
> + KERN_RC5X = 4, /* Philips RC5x protocol */
> + KERN_RC5_SZ = 5, /* StreamZap variant of RC5 */
> + KERN_JVC = 6, /* JVC protocol */
> + KERN_SONY12 = 7, /* Sony 12 bit protocol */
> + KERN_SONY15 = 8, /* Sony 15 bit protocol */
> + KERN_SONY20 = 9, /* Sony 20 bit protocol */
> + KERN_NEC = 10, /* NEC protocol */
> + KERN_SANYO = 11, /* Sanyo protocol */
> + KERN_MCE_KBD = 12, /* RC6-ish MCE keyboard/mouse */
> + KERN_RC6_0 = 13, /* Philips RC6-0-16 protocol */
> + KERN_RC6_6A_20 = 14, /* Philips RC6-6A-20 protocol */
> + KERN_RC6_6A_24 = 15, /* Philips RC6-6A-24 protocol */
> + KERN_RC6_6A_32 = 16, /* Philips RC6-6A-32 protocol */
> + KERN_RC6_MCE = 17, /* MCE (Philips RC6-6A-32 subtype) protocol */
> + KERN_SHARP = 18, /* Sharp protocol */
> + KERN_XMP = 19, /* XMP protocol */
> + KERN_INVALID = 31, /* internal, no real protocol number */
> +};
> +
> struct protocol_map_entry {
> const char *name;
> const char *sysfs1_name;
> enum sysfs_protocols sysfs_protocol;
> + enum kernel_protocol kernel_protocol;
> };
>
> const struct protocol_map_entry protocol_map[] = {
> - { "unknown", NULL, SYSFS_UNKNOWN },
> - { "other", NULL, SYSFS_OTHER },
> - { "lirc", NULL, SYSFS_LIRC },
> - { "rc-5", "/rc5_decoder", SYSFS_RC5 },
> - { "rc5", NULL, SYSFS_RC5 },
> - { "rc-5x", NULL, SYSFS_INVALID },
> - { "rc5x", NULL, SYSFS_INVALID },
> - { "jvc", "/jvc_decoder", SYSFS_JVC },
> - { "sony", "/sony_decoder",SYSFS_SONY },
> - { "sony12", NULL, SYSFS_INVALID },
> - { "sony15", NULL, SYSFS_INVALID },
> - { "sony20", NULL, SYSFS_INVALID },
> - { "nec", "/nec_decoder", SYSFS_NEC },
> - { "sanyo", NULL, SYSFS_SANYO },
> - { "mce-kbd", NULL, SYSFS_MCE_KBD },
> - { "mce_kbd", NULL, SYSFS_MCE_KBD },
> - { "rc-6", "/rc6_decoder", SYSFS_RC6 },
> - { "rc6", NULL, SYSFS_RC6 },
> - { "rc-6-0", NULL, SYSFS_INVALID },
> - { "rc-6-6a-20", NULL, SYSFS_INVALID },
> - { "rc-6-6a-24", NULL, SYSFS_INVALID },
> - { "rc-6-6a-32", NULL, SYSFS_INVALID },
> - { "rc-6-mce", NULL, SYSFS_INVALID },
> - { "sharp", NULL, SYSFS_SHARP },
> - { "xmp", "/xmp_decoder", SYSFS_XMP },
> - { NULL, NULL, SYSFS_INVALID },
> + { "unknown", NULL, SYSFS_UNKNOWN, KERN_UNKNOWN },
> + { "other", NULL, SYSFS_OTHER, KERN_OTHER },
> + { "lirc", NULL, SYSFS_LIRC, KERN_LIRC },
> + { "rc-5", "/rc5_decoder", SYSFS_RC5, KERN_RC5 },
> + { "rc5", NULL, SYSFS_RC5, KERN_RC5 },
> + { "rc-5x", NULL, SYSFS_INVALID, KERN_RC5X },
> + { "rc5x", NULL, SYSFS_INVALID, KERN_RC5X },
> + { "jvc", "/jvc_decoder", SYSFS_JVC, KERN_JVC },
> + { "sony", "/sony_decoder",SYSFS_SONY, KERN_INVALID },
> + { "sony12", NULL, SYSFS_INVALID, KERN_SONY12 },
> + { "sony15", NULL, SYSFS_INVALID, KERN_SONY15 },
> + { "sony20", NULL, SYSFS_INVALID, KERN_SONY20 },
> + { "nec", "/nec_decoder", SYSFS_NEC, KERN_NEC },
> + { "sanyo", NULL, SYSFS_SANYO, KERN_SANYO },
> + { "mce-kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
> + { "mce_kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
> + { "rc-6", "/rc6_decoder", SYSFS_RC6, KERN_INVALID },
> + { "rc6", NULL, SYSFS_RC6, KERN_INVALID },
> + { "rc-6-0", NULL, SYSFS_INVALID, KERN_RC6_0 },
> + { "rc-6-6a-20", NULL, SYSFS_INVALID, KERN_RC6_6A_20 },
> + { "rc-6-6a-24", NULL, SYSFS_INVALID, KERN_RC6_6A_24 },
> + { "rc-6-6a-32", NULL, SYSFS_INVALID, KERN_RC6_6A_32 },
> + { "rc-6-mce", NULL, SYSFS_INVALID, KERN_RC6_MCE },
> + { "sharp", NULL, SYSFS_SHARP, KERN_SHARP },
> + { "xmp", "/xmp_decoder", SYSFS_XMP, KERN_XMP },
> + { NULL, NULL, SYSFS_INVALID, KERN_INVALID },
> +};
> +
> +struct keytable_entry {
> + u_int32_t scancode;
> + u_int32_t keycode;
> + enum kernel_protocol protocol;
> + struct keytable_entry *next;
> };
>
> +struct keytable_entry *keytable = NULL;
> +
> +
> static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allowed)
> {
> const struct protocol_map_entry *pme;
> @@ -162,6 +206,21 @@ static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allo
> return SYSFS_INVALID;
> }
>
> +static enum kernel_protocol parse_kernel_protocol(const char *name)
> +{
> + const struct protocol_map_entry *pme;
> +
> + if (!name)
> + return KERN_INVALID;
> +
> + for (pme = protocol_map; pme->name; pme++) {
> + if (!strcasecmp(name, pme->name))
> + return pme->kernel_protocol;
> + }
> +
> + return KERN_INVALID;
> +}
> +
> static void write_sysfs_protocols(enum sysfs_protocols protocols, FILE *fp, const char *fmt)
> {
> const struct protocol_map_entry *pme;
> @@ -197,6 +256,7 @@ static const char doc[] = N_(
> " SYSDEV - the ir class as found at /sys/class/rc\n"
> " TABLE - a file with a set of scancode=keycode value pairs\n"
> " SCANKEY - a set of scancode1=keycode1,scancode2=keycode2.. value pairs\n"
> + " or (experimentally) a list of protocol1:scancode1=keycode1,protocol2:scancode2=keycode2...triplets\n"
> " PROTOCOL - protocol name (nec, rc-5, rc-6, jvc, sony, sanyo, rc-5-sz, lirc,\n"
> " sharp, mce_kbd, xmp, other, all) to be enabled\n"
> " DELAY - Delay before repeating a keystroke\n"
> @@ -447,7 +507,6 @@ err_einval:
> static error_t parse_opt(int k, char *arg, struct argp_state *state)
> {
> char *p;
> - long key;
> int rc;
>
> switch (k) {
> @@ -492,51 +551,69 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
> break;
> }
> case 'k':
> - p = strtok(arg, ":=");
> - do {
> + for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
> + char *protocol_str;
> + enum kernel_protocol protocol = KERN_INVALID;
> + long long int scancode;
> + char *keycode_str;
> + long keycode;
> struct keytable_entry *ke;
>
> - if (!p)
> - goto err_inval;
> -
> - ke = calloc(1, sizeof(*ke));
> - if (!ke) {
> - perror(_("No memory!\n"));
> - return ENOMEM;
> + errno = 0;
> + /* New format - protocol:scancode=keycode */
> + if (sscanf(p, " %m[^:] : %lli = %ms", &protocol_str, &scancode, &keycode_str) != 3) {
> + if (errno != 0) {
> + fprintf(stderr, _("sscanf failed!\n"));
> + return errno;
> + }
> +
> + /* Old format - scancode=keycode */
> + protocol_str = NULL;
> + if (sscanf(p, " %lli = %ms", &scancode, &keycode_str) != 2) {
> + if (errno != 0) {
> + fprintf(stderr, _("sscanf failed!\n"));
> + return errno;
> + }
> + goto err_inval;
> + }
> }
>
> - ke->scancode = strtoul(p, NULL, 0);
> - if (errno) {
> - free(ke);
> - goto err_inval;
> + keycode = parse_code(keycode_str);
> + if (keycode == -1) {
> + errno = 0;
> + keycode = strtoul(keycode_str, NULL, 0);
> + if (errno)
> + keycode = -1;
> }
> + free(keycode_str);
>
> - p = strtok(NULL, ",;");
> - if (!p) {
> - free(ke);
> - goto err_inval;
> - }
> + if (protocol_str) {
> + protocol = parse_kernel_protocol(protocol_str);
> + free(protocol_str);
>
> - key = parse_code(p);
> - if (key == -1) {
> - key = strtol(p, NULL, 0);
> - if (errno) {
> - free(ke);
> + if (protocol == KERN_INVALID)
> goto err_inval;
> - }
> }
>
> - ke->keycode = key;
> + if (keycode == -1 || scancode < 0)
> + goto err_inval;
>
> - if (debug)
> - fprintf(stderr, _("scancode 0x%04x=%u\n"),
> - ke->scancode, ke->keycode);
> + ke = calloc(1, sizeof(*ke));
> + if (!ke) {
> + perror(_("No memory!\n"));
> + return ENOMEM;
> + }
>
> + ke->scancode = scancode;
> + ke->keycode = keycode;
> + ke->protocol = protocol;
> ke->next = keytable;
> keytable = ke;
>
> - p = strtok(NULL, ":=");
> - } while (p);
> + if (debug)
> + fprintf(stderr, _("scancode %i:0x%04x=%u\n"),
> + ke->protocol, ke->scancode, ke->keycode);
> + }
> break;
> case 'p':
> for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
> @@ -579,21 +656,24 @@ static struct argp argp = {
> .doc = doc,
> };
>
> -static void prtcode(int *codes)
> +static void print_mapping(enum kernel_protocol protocol, unsigned scancode, unsigned keycode)
> {
> struct parse_event *p;
>
> + if (protocol != KERN_INVALID)
> + printf(_("protocol 0x%04x, "), protocol);
> +
> for (p = key_events; p->name != NULL; p++) {
> - if (p->value == (unsigned)codes[1]) {
> - printf(_("scancode 0x%04x = %s (0x%02x)\n"), codes[0], p->name, codes[1]);
> + if (p->value == keycode) {
> + printf(_("scancode 0x%04x = %s (0x%02x)\n"), scancode, p->name, keycode);
> return;
> }
> }
>
> - if (isprint (codes[1]))
> - printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), codes[0], codes[1], codes[1]);
> + if (isprint(keycode))
> + printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), scancode, keycode, keycode);
> else
> - printf(_("scancode 0x%04x = 0x%02x\n"), codes[0], codes[1]);
> + printf(_("scancode 0x%04x = 0x%02x\n"), scancode, keycode);
> }
>
> static void free_names(struct sysfs_names *names)
> @@ -1201,12 +1281,30 @@ static int add_keys(int fd)
> int write_cnt = 0;
> struct keytable_entry *ke;
> unsigned codes[2];
> + struct rc_keymap_entry rke;
>
> for (ke = keytable; ke; ke = ke->next) {
> write_cnt++;
> if (debug)
> - fprintf(stderr, "\t%04x=%04x\n",
> - ke->scancode, ke->keycode);
> + fprintf(stderr, "\t%u:%04x=%04x\n",
> + ke->protocol, ke->scancode, ke->keycode);
> +
> + if (ke->protocol != KERN_INVALID) {
> + memset(&rke, '\0', sizeof(rke));
> + rke.len = sizeof(rke.rc);
> + rke.keycode = ke->keycode;
> + rke.rc.protocol = ke->protocol;
> + rke.rc.scancode = ke->scancode;
> +
> + if (debug)
> + fprintf(stderr, _("Attempting new EVIOCSKEYCODE_V2 ioctl\n"));
> +
> + if (ioctl(fd, EVIOCSKEYCODE_V2, &rke) == 0)
> + continue;
> +
> + if (debug)
> + fprintf(stderr, _("New EVIOCSKEYCODE_V2 ioctl failed\n"));
> + }
>
> codes[0] = ke->scancode;
> codes[1] = ke->keycode;
> @@ -1329,7 +1427,7 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
> if (ioctl(fd, EVIOCGKEYCODE, codes) == -1)
> perror("EVIOCGKEYCODE");
> else if (codes[1] != KEY_RESERVED)
> - prtcode(codes);
> + print_mapping(KERN_INVALID, codes[0], codes[1]);
> }
> }
> display_proto(rc_dev);
> @@ -1337,27 +1435,45 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
>
> static void display_table_v2(struct rc_device *rc_dev, int fd)
> {
> + struct input_keymap_entry_v2 ike;
> + struct rc_keymap_entry rke;
> + bool first = true, rke_supported = true;
> + u_int32_t scancode;
> int i;
> - struct input_keymap_entry_v2 entry;
> - int codes[2];
>
> - memset(&entry, '\0', sizeof(entry));
> - i = 0;
> - do {
> - entry.flags = KEYMAP_BY_INDEX;
> - entry.index = i;
> - entry.len = sizeof(u_int32_t);
> + for (i = 0; ; i++) {
> + if (first || rke_supported) {
> + memset(&rke, '\0', sizeof(rke));
> + rke.flags = KEYMAP_BY_INDEX;
> + rke.index = i;
> + rke.len = sizeof(rke.rc);
>
> - if (ioctl(fd, EVIOCGKEYCODE_V2, &entry) == -1)
> + if (ioctl(fd, EVIOCGKEYCODE_V2, &rke) == -1) {
> + if (first)
> + rke_supported = false;
> + else
> + break;
> + }
> +
> + first = false;
> + if (rke_supported) {
> + print_mapping(rke.rc.protocol, rke.rc.scancode, rke.keycode);
> + continue;
> + }
> + }
> +
> + memset(&ike, '\0', sizeof(ike));
> + ike.flags = KEYMAP_BY_INDEX;
> + ike.index = i;
> + ike.len = sizeof(scancode);
> +
> + if (ioctl(fd, EVIOCGKEYCODE_V2, &ike) == -1)
> break;
>
> /* FIXME: Extend it to support scancodes > 32 bits */
> - memcpy(&codes[0], entry.scancode, sizeof(codes[0]));
> - codes[1] = entry.keycode;
> -
> - prtcode(codes);
> - i++;
> - } while (1);
> + memcpy(&scancode, ike.scancode, sizeof(scancode));
> + print_mapping(KERN_INVALID, scancode, ike.keycode);
> + }
> display_proto(rc_dev);
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings
2015-05-14 21:24 ` Mauro Carvalho Chehab
@ 2015-05-19 21:36 ` David Härdeman
0 siblings, 0 replies; 7+ messages in thread
From: David Härdeman @ 2015-05-19 21:36 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media
On Thu, May 14, 2015 at 06:24:46PM -0300, Mauro Carvalho Chehab wrote:
>Em Mon, 06 Apr 2015 13:26:18 +0200
>David Härdeman <david@hardeman.nu> escreveu:
>
>> Introduce a list of "kernel" ir protocols (e.g. "sony12" instead of "sony")
>> and extend the set-key command to ir-keytable to allow for a mapping of the
>> form "protocol:scancode=keycode" in addition to the old "scancode=keycode"
>> format. The code automatically falls back to the old behaviour if the
>> kernel doesn't support the new approach with protocols.
>>
>> The read command is also updated to show the protocol information if the
>> kernel supports it.
>
>
>I applied patches 1 to 3 of this series, as they are not based on any
>new feature.
>
>This patch, however, needs to wait for the Kernel patch to be acked, and
>may be modified, depending on the review process.
>
>I'll mark it at patchwork as RFC. Please re-submit after we merge the
>Kernel changes.
Agreed :)
>
>Thanks,
>Mauro
>
>>
>> Signed-off-by: David Härdeman <david@hardeman.nu>
>> ---
>> utils/keytable/keytable.c | 288 ++++++++++++++++++++++++++++++++-------------
>> 1 file changed, 202 insertions(+), 86 deletions(-)
>>
>> diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
>> index 63eea2e..fd50095 100644
>> --- a/utils/keytable/keytable.c
>> +++ b/utils/keytable/keytable.c
>> @@ -55,13 +55,22 @@ struct input_keymap_entry_v2 {
>> #define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry_v2)
>> #endif
>>
>> -struct keytable_entry {
>> - u_int32_t scancode;
>> - u_int32_t keycode;
>> - struct keytable_entry *next;
>> +struct rc_scancode {
>> + u_int16_t protocol;
>> + u_int16_t reserved[3];
>> + u_int64_t scancode;
>> };
>>
>> -struct keytable_entry *keytable = NULL;
>> +struct rc_keymap_entry {
>> + u_int8_t flags;
>> + u_int8_t len;
>> + u_int16_t index;
>> + u_int32_t keycode;
>> + union {
>> + struct rc_scancode rc;
>> + u_int8_t raw[32];
>> + };
>> +};
>>
>> struct uevents {
>> char *key;
>> @@ -109,41 +118,76 @@ enum sysfs_protocols {
>> SYSFS_INVALID = 0,
>> };
>>
>> +enum kernel_protocol {
>> + KERN_UNKNOWN = 0, /* Protocol not known */
>> + KERN_OTHER = 1, /* Protocol known but proprietary */
>> + KERN_LIRC = 2, /* Pass raw IR to lirc userspace */
>> + KERN_RC5 = 3, /* Philips RC5 protocol */
>> + KERN_RC5X = 4, /* Philips RC5x protocol */
>> + KERN_RC5_SZ = 5, /* StreamZap variant of RC5 */
>> + KERN_JVC = 6, /* JVC protocol */
>> + KERN_SONY12 = 7, /* Sony 12 bit protocol */
>> + KERN_SONY15 = 8, /* Sony 15 bit protocol */
>> + KERN_SONY20 = 9, /* Sony 20 bit protocol */
>> + KERN_NEC = 10, /* NEC protocol */
>> + KERN_SANYO = 11, /* Sanyo protocol */
>> + KERN_MCE_KBD = 12, /* RC6-ish MCE keyboard/mouse */
>> + KERN_RC6_0 = 13, /* Philips RC6-0-16 protocol */
>> + KERN_RC6_6A_20 = 14, /* Philips RC6-6A-20 protocol */
>> + KERN_RC6_6A_24 = 15, /* Philips RC6-6A-24 protocol */
>> + KERN_RC6_6A_32 = 16, /* Philips RC6-6A-32 protocol */
>> + KERN_RC6_MCE = 17, /* MCE (Philips RC6-6A-32 subtype) protocol */
>> + KERN_SHARP = 18, /* Sharp protocol */
>> + KERN_XMP = 19, /* XMP protocol */
>> + KERN_INVALID = 31, /* internal, no real protocol number */
>> +};
>> +
>> struct protocol_map_entry {
>> const char *name;
>> const char *sysfs1_name;
>> enum sysfs_protocols sysfs_protocol;
>> + enum kernel_protocol kernel_protocol;
>> };
>>
>> const struct protocol_map_entry protocol_map[] = {
>> - { "unknown", NULL, SYSFS_UNKNOWN },
>> - { "other", NULL, SYSFS_OTHER },
>> - { "lirc", NULL, SYSFS_LIRC },
>> - { "rc-5", "/rc5_decoder", SYSFS_RC5 },
>> - { "rc5", NULL, SYSFS_RC5 },
>> - { "rc-5x", NULL, SYSFS_INVALID },
>> - { "rc5x", NULL, SYSFS_INVALID },
>> - { "jvc", "/jvc_decoder", SYSFS_JVC },
>> - { "sony", "/sony_decoder",SYSFS_SONY },
>> - { "sony12", NULL, SYSFS_INVALID },
>> - { "sony15", NULL, SYSFS_INVALID },
>> - { "sony20", NULL, SYSFS_INVALID },
>> - { "nec", "/nec_decoder", SYSFS_NEC },
>> - { "sanyo", NULL, SYSFS_SANYO },
>> - { "mce-kbd", NULL, SYSFS_MCE_KBD },
>> - { "mce_kbd", NULL, SYSFS_MCE_KBD },
>> - { "rc-6", "/rc6_decoder", SYSFS_RC6 },
>> - { "rc6", NULL, SYSFS_RC6 },
>> - { "rc-6-0", NULL, SYSFS_INVALID },
>> - { "rc-6-6a-20", NULL, SYSFS_INVALID },
>> - { "rc-6-6a-24", NULL, SYSFS_INVALID },
>> - { "rc-6-6a-32", NULL, SYSFS_INVALID },
>> - { "rc-6-mce", NULL, SYSFS_INVALID },
>> - { "sharp", NULL, SYSFS_SHARP },
>> - { "xmp", "/xmp_decoder", SYSFS_XMP },
>> - { NULL, NULL, SYSFS_INVALID },
>> + { "unknown", NULL, SYSFS_UNKNOWN, KERN_UNKNOWN },
>> + { "other", NULL, SYSFS_OTHER, KERN_OTHER },
>> + { "lirc", NULL, SYSFS_LIRC, KERN_LIRC },
>> + { "rc-5", "/rc5_decoder", SYSFS_RC5, KERN_RC5 },
>> + { "rc5", NULL, SYSFS_RC5, KERN_RC5 },
>> + { "rc-5x", NULL, SYSFS_INVALID, KERN_RC5X },
>> + { "rc5x", NULL, SYSFS_INVALID, KERN_RC5X },
>> + { "jvc", "/jvc_decoder", SYSFS_JVC, KERN_JVC },
>> + { "sony", "/sony_decoder",SYSFS_SONY, KERN_INVALID },
>> + { "sony12", NULL, SYSFS_INVALID, KERN_SONY12 },
>> + { "sony15", NULL, SYSFS_INVALID, KERN_SONY15 },
>> + { "sony20", NULL, SYSFS_INVALID, KERN_SONY20 },
>> + { "nec", "/nec_decoder", SYSFS_NEC, KERN_NEC },
>> + { "sanyo", NULL, SYSFS_SANYO, KERN_SANYO },
>> + { "mce-kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
>> + { "mce_kbd", NULL, SYSFS_MCE_KBD, KERN_MCE_KBD },
>> + { "rc-6", "/rc6_decoder", SYSFS_RC6, KERN_INVALID },
>> + { "rc6", NULL, SYSFS_RC6, KERN_INVALID },
>> + { "rc-6-0", NULL, SYSFS_INVALID, KERN_RC6_0 },
>> + { "rc-6-6a-20", NULL, SYSFS_INVALID, KERN_RC6_6A_20 },
>> + { "rc-6-6a-24", NULL, SYSFS_INVALID, KERN_RC6_6A_24 },
>> + { "rc-6-6a-32", NULL, SYSFS_INVALID, KERN_RC6_6A_32 },
>> + { "rc-6-mce", NULL, SYSFS_INVALID, KERN_RC6_MCE },
>> + { "sharp", NULL, SYSFS_SHARP, KERN_SHARP },
>> + { "xmp", "/xmp_decoder", SYSFS_XMP, KERN_XMP },
>> + { NULL, NULL, SYSFS_INVALID, KERN_INVALID },
>> +};
>> +
>> +struct keytable_entry {
>> + u_int32_t scancode;
>> + u_int32_t keycode;
>> + enum kernel_protocol protocol;
>> + struct keytable_entry *next;
>> };
>>
>> +struct keytable_entry *keytable = NULL;
>> +
>> +
>> static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allowed)
>> {
>> const struct protocol_map_entry *pme;
>> @@ -162,6 +206,21 @@ static enum sysfs_protocols parse_sysfs_protocol(const char *name, bool all_allo
>> return SYSFS_INVALID;
>> }
>>
>> +static enum kernel_protocol parse_kernel_protocol(const char *name)
>> +{
>> + const struct protocol_map_entry *pme;
>> +
>> + if (!name)
>> + return KERN_INVALID;
>> +
>> + for (pme = protocol_map; pme->name; pme++) {
>> + if (!strcasecmp(name, pme->name))
>> + return pme->kernel_protocol;
>> + }
>> +
>> + return KERN_INVALID;
>> +}
>> +
>> static void write_sysfs_protocols(enum sysfs_protocols protocols, FILE *fp, const char *fmt)
>> {
>> const struct protocol_map_entry *pme;
>> @@ -197,6 +256,7 @@ static const char doc[] = N_(
>> " SYSDEV - the ir class as found at /sys/class/rc\n"
>> " TABLE - a file with a set of scancode=keycode value pairs\n"
>> " SCANKEY - a set of scancode1=keycode1,scancode2=keycode2.. value pairs\n"
>> + " or (experimentally) a list of protocol1:scancode1=keycode1,protocol2:scancode2=keycode2...triplets\n"
>> " PROTOCOL - protocol name (nec, rc-5, rc-6, jvc, sony, sanyo, rc-5-sz, lirc,\n"
>> " sharp, mce_kbd, xmp, other, all) to be enabled\n"
>> " DELAY - Delay before repeating a keystroke\n"
>> @@ -447,7 +507,6 @@ err_einval:
>> static error_t parse_opt(int k, char *arg, struct argp_state *state)
>> {
>> char *p;
>> - long key;
>> int rc;
>>
>> switch (k) {
>> @@ -492,51 +551,69 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state)
>> break;
>> }
>> case 'k':
>> - p = strtok(arg, ":=");
>> - do {
>> + for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
>> + char *protocol_str;
>> + enum kernel_protocol protocol = KERN_INVALID;
>> + long long int scancode;
>> + char *keycode_str;
>> + long keycode;
>> struct keytable_entry *ke;
>>
>> - if (!p)
>> - goto err_inval;
>> -
>> - ke = calloc(1, sizeof(*ke));
>> - if (!ke) {
>> - perror(_("No memory!\n"));
>> - return ENOMEM;
>> + errno = 0;
>> + /* New format - protocol:scancode=keycode */
>> + if (sscanf(p, " %m[^:] : %lli = %ms", &protocol_str, &scancode, &keycode_str) != 3) {
>> + if (errno != 0) {
>> + fprintf(stderr, _("sscanf failed!\n"));
>> + return errno;
>> + }
>> +
>> + /* Old format - scancode=keycode */
>> + protocol_str = NULL;
>> + if (sscanf(p, " %lli = %ms", &scancode, &keycode_str) != 2) {
>> + if (errno != 0) {
>> + fprintf(stderr, _("sscanf failed!\n"));
>> + return errno;
>> + }
>> + goto err_inval;
>> + }
>> }
>>
>> - ke->scancode = strtoul(p, NULL, 0);
>> - if (errno) {
>> - free(ke);
>> - goto err_inval;
>> + keycode = parse_code(keycode_str);
>> + if (keycode == -1) {
>> + errno = 0;
>> + keycode = strtoul(keycode_str, NULL, 0);
>> + if (errno)
>> + keycode = -1;
>> }
>> + free(keycode_str);
>>
>> - p = strtok(NULL, ",;");
>> - if (!p) {
>> - free(ke);
>> - goto err_inval;
>> - }
>> + if (protocol_str) {
>> + protocol = parse_kernel_protocol(protocol_str);
>> + free(protocol_str);
>>
>> - key = parse_code(p);
>> - if (key == -1) {
>> - key = strtol(p, NULL, 0);
>> - if (errno) {
>> - free(ke);
>> + if (protocol == KERN_INVALID)
>> goto err_inval;
>> - }
>> }
>>
>> - ke->keycode = key;
>> + if (keycode == -1 || scancode < 0)
>> + goto err_inval;
>>
>> - if (debug)
>> - fprintf(stderr, _("scancode 0x%04x=%u\n"),
>> - ke->scancode, ke->keycode);
>> + ke = calloc(1, sizeof(*ke));
>> + if (!ke) {
>> + perror(_("No memory!\n"));
>> + return ENOMEM;
>> + }
>>
>> + ke->scancode = scancode;
>> + ke->keycode = keycode;
>> + ke->protocol = protocol;
>> ke->next = keytable;
>> keytable = ke;
>>
>> - p = strtok(NULL, ":=");
>> - } while (p);
>> + if (debug)
>> + fprintf(stderr, _("scancode %i:0x%04x=%u\n"),
>> + ke->protocol, ke->scancode, ke->keycode);
>> + }
>> break;
>> case 'p':
>> for (p = strtok(arg, ",;"); p; p = strtok(NULL, ",;")) {
>> @@ -579,21 +656,24 @@ static struct argp argp = {
>> .doc = doc,
>> };
>>
>> -static void prtcode(int *codes)
>> +static void print_mapping(enum kernel_protocol protocol, unsigned scancode, unsigned keycode)
>> {
>> struct parse_event *p;
>>
>> + if (protocol != KERN_INVALID)
>> + printf(_("protocol 0x%04x, "), protocol);
>> +
>> for (p = key_events; p->name != NULL; p++) {
>> - if (p->value == (unsigned)codes[1]) {
>> - printf(_("scancode 0x%04x = %s (0x%02x)\n"), codes[0], p->name, codes[1]);
>> + if (p->value == keycode) {
>> + printf(_("scancode 0x%04x = %s (0x%02x)\n"), scancode, p->name, keycode);
>> return;
>> }
>> }
>>
>> - if (isprint (codes[1]))
>> - printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), codes[0], codes[1], codes[1]);
>> + if (isprint(keycode))
>> + printf(_("scancode 0x%04x = '%c' (0x%02x)\n"), scancode, keycode, keycode);
>> else
>> - printf(_("scancode 0x%04x = 0x%02x\n"), codes[0], codes[1]);
>> + printf(_("scancode 0x%04x = 0x%02x\n"), scancode, keycode);
>> }
>>
>> static void free_names(struct sysfs_names *names)
>> @@ -1201,12 +1281,30 @@ static int add_keys(int fd)
>> int write_cnt = 0;
>> struct keytable_entry *ke;
>> unsigned codes[2];
>> + struct rc_keymap_entry rke;
>>
>> for (ke = keytable; ke; ke = ke->next) {
>> write_cnt++;
>> if (debug)
>> - fprintf(stderr, "\t%04x=%04x\n",
>> - ke->scancode, ke->keycode);
>> + fprintf(stderr, "\t%u:%04x=%04x\n",
>> + ke->protocol, ke->scancode, ke->keycode);
>> +
>> + if (ke->protocol != KERN_INVALID) {
>> + memset(&rke, '\0', sizeof(rke));
>> + rke.len = sizeof(rke.rc);
>> + rke.keycode = ke->keycode;
>> + rke.rc.protocol = ke->protocol;
>> + rke.rc.scancode = ke->scancode;
>> +
>> + if (debug)
>> + fprintf(stderr, _("Attempting new EVIOCSKEYCODE_V2 ioctl\n"));
>> +
>> + if (ioctl(fd, EVIOCSKEYCODE_V2, &rke) == 0)
>> + continue;
>> +
>> + if (debug)
>> + fprintf(stderr, _("New EVIOCSKEYCODE_V2 ioctl failed\n"));
>> + }
>>
>> codes[0] = ke->scancode;
>> codes[1] = ke->keycode;
>> @@ -1329,7 +1427,7 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
>> if (ioctl(fd, EVIOCGKEYCODE, codes) == -1)
>> perror("EVIOCGKEYCODE");
>> else if (codes[1] != KEY_RESERVED)
>> - prtcode(codes);
>> + print_mapping(KERN_INVALID, codes[0], codes[1]);
>> }
>> }
>> display_proto(rc_dev);
>> @@ -1337,27 +1435,45 @@ static void display_table_v1(struct rc_device *rc_dev, int fd)
>>
>> static void display_table_v2(struct rc_device *rc_dev, int fd)
>> {
>> + struct input_keymap_entry_v2 ike;
>> + struct rc_keymap_entry rke;
>> + bool first = true, rke_supported = true;
>> + u_int32_t scancode;
>> int i;
>> - struct input_keymap_entry_v2 entry;
>> - int codes[2];
>>
>> - memset(&entry, '\0', sizeof(entry));
>> - i = 0;
>> - do {
>> - entry.flags = KEYMAP_BY_INDEX;
>> - entry.index = i;
>> - entry.len = sizeof(u_int32_t);
>> + for (i = 0; ; i++) {
>> + if (first || rke_supported) {
>> + memset(&rke, '\0', sizeof(rke));
>> + rke.flags = KEYMAP_BY_INDEX;
>> + rke.index = i;
>> + rke.len = sizeof(rke.rc);
>>
>> - if (ioctl(fd, EVIOCGKEYCODE_V2, &entry) == -1)
>> + if (ioctl(fd, EVIOCGKEYCODE_V2, &rke) == -1) {
>> + if (first)
>> + rke_supported = false;
>> + else
>> + break;
>> + }
>> +
>> + first = false;
>> + if (rke_supported) {
>> + print_mapping(rke.rc.protocol, rke.rc.scancode, rke.keycode);
>> + continue;
>> + }
>> + }
>> +
>> + memset(&ike, '\0', sizeof(ike));
>> + ike.flags = KEYMAP_BY_INDEX;
>> + ike.index = i;
>> + ike.len = sizeof(scancode);
>> +
>> + if (ioctl(fd, EVIOCGKEYCODE_V2, &ike) == -1)
>> break;
>>
>> /* FIXME: Extend it to support scancodes > 32 bits */
>> - memcpy(&codes[0], entry.scancode, sizeof(codes[0]));
>> - codes[1] = entry.keycode;
>> -
>> - prtcode(codes);
>> - i++;
>> - } while (1);
>> + memcpy(&scancode, ike.scancode, sizeof(scancode));
>> + print_mapping(KERN_INVALID, scancode, ike.keycode);
>> + }
>> display_proto(rc_dev);
>> }
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
David Härdeman
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-05-19 22:06 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-06 11:25 [PATCH 0/4] Add protocol support to ir-keytable David Härdeman
2015-04-06 11:26 ` [PATCH 1/4] ir-keytable: clarify the meaning of ir protocols David Härdeman
2015-04-06 11:26 ` [PATCH 2/4] ir-keytable: replace more sysfs if-else code with loops David Härdeman
2015-04-06 11:26 ` [PATCH 3/4] ir-keytable: cleanup keytable code David Härdeman
2015-04-06 11:26 ` [PATCH 4/4] ir-keytable: allow protocol for scancode-keycode mappings David Härdeman
2015-05-14 21:24 ` Mauro Carvalho Chehab
2015-05-19 21:36 ` David Härdeman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).