All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR
@ 2017-09-26 20:23 Sean Young
  2017-09-26 20:23 ` [PATCH 2/5] ir-ctl: show scancode lirc features Sean Young
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Sean Young @ 2017-09-26 20:23 UTC (permalink / raw)
  To: linux-media

This simplifies dealing with kernel encoders and raw IR, and does
not make much sense anyway.

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/ir-ctl.1.in |  7 ++-----
 utils/ir-ctl/ir-ctl.c    | 12 +++++++++---
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/utils/ir-ctl/ir-ctl.1.in b/utils/ir-ctl/ir-ctl.1.in
index 05550fb1..401521da 100644
--- a/utils/ir-ctl/ir-ctl.1.in
+++ b/utils/ir-ctl/ir-ctl.1.in
@@ -168,11 +168,8 @@ carrier. The above can be written as:
 .PP
 	scancode rc5:0x1e01
 .PP
-Do not specify scancodes with different protocols in one file, as the
-carrier might differ and the transmitter cannot send this. Multiple
-scancodes can be specified in one file but ensure that the rules for the
-protocol are met by inserting an appropriate space between them. Also,
-there are limits to what lirc devices can send in one go.
+If you specify a scancode in a pulse space file, no other pulse, space or
+even carrier may be specified.
 .PP
 .SS Supported Protocols
 A scancode with protocol can be specified on the command line or in the
diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index d3cce6a6..7dcdd983 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -187,7 +187,7 @@ static unsigned parse_emitters(char *p)
 
 static struct file *read_file(const char *fname)
 {
-	bool expect_pulse = true;
+	bool expect_pulse = true, seen_scancode = false;
 	int lineno = 0, lastspace = 0;
 	char line[1024];
 	int len = 0;
@@ -229,8 +229,8 @@ static struct file *read_file(const char *fname)
 			unsigned scancode, carrier;
 			char *scancodestr;
 
-			if (!expect_pulse) {
-				fprintf(stderr, _("error: %s:%d: space must precede scancode\n"), fname, lineno);
+			if (len) {
+				fprintf(stderr, _("error: %s:%d: scancode must be appear in file by itself\n"), fname, lineno);
 				return NULL;
 			}
 
@@ -269,6 +269,7 @@ static struct file *read_file(const char *fname)
 				f->carrier = carrier;
 
 			len += protocol_encode(proto, scancode, f->buf);
+			seen_scancode = true;
 			continue;
 		}
 
@@ -284,6 +285,11 @@ static struct file *read_file(const char *fname)
 			continue;
 		}
 
+		if (seen_scancode) {
+			fprintf(stderr, _("error: %s:%d: scancode must be appear in file by itself\n"), fname, lineno);
+			return NULL;
+		}
+
 		if (strcmp(keyword, "space") == 0) {
 			if (expect_pulse) {
 				if (len == 0) {
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/5] ir-ctl: show scancode lirc features
  2017-09-26 20:23 [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR Sean Young
@ 2017-09-26 20:23 ` Sean Young
  2017-09-26 20:23 ` [PATCH 3/5] ir-ctl: use lirc scancode sending Sean Young
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Young @ 2017-09-26 20:23 UTC (permalink / raw)
  To: linux-media

Report if a lirc devices can receive or send using scancodes.

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/ir-ctl.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index 7dcdd983..32d7162f 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -691,7 +691,12 @@ static void lirc_features(struct arguments *args, int fd, unsigned features)
 			fprintf(stderr, _("warning: %s: unexpected error while retrieving resolution: %m\n"), dev);
 	}
 
+	bool can_receive = false;
 	printf(_("Receive features %s:\n"), dev);
+	if (features & LIRC_CAN_REC_SCANCODE) {
+		printf(_(" - Device can receive scancodes\n"));
+		can_receive = true;
+	}
 	if (features & LIRC_CAN_REC_MODE2) {
 		printf(_(" - Device can receive raw IR\n"));
 		if (resolution)
@@ -721,13 +726,22 @@ static void lirc_features(struct arguments *args, int fd, unsigned features)
 			if (min_timeout || max_timeout)
 				printf(_(" - Can set recording timeout min:%u microseconds max:%u microseconds\n"), min_timeout, max_timeout);
 		}
-	} else if (features & LIRC_CAN_REC_LIRCCODE) {
+		can_receive = true;
+	}
+	if (features & LIRC_CAN_REC_LIRCCODE) {
 		printf(_(" - Device can receive using device dependent LIRCCODE mode (not supported)\n"));
-	} else {
-		printf(_(" - Device cannot receive\n"));
+		can_receive = true;
 	}
 
+	if (!can_receive)
+		printf(_(" - Device cannot receive\n"));
+
+	bool can_send = false;
 	printf(_("Send features %s:\n"), dev);
+	if (features & LIRC_CAN_SEND_SCANCODE) {
+		printf(_(" - Device can send scancodes\n"));
+		can_send = true;
+	}
 	if (features & LIRC_CAN_SEND_PULSE) {
 		printf(_(" - Device can send raw IR\n"));
 		if (features & LIRC_CAN_SET_SEND_CARRIER)
@@ -744,11 +758,15 @@ static void lirc_features(struct arguments *args, int fd, unsigned features)
 			else
 				printf(_(" - Set transmitter (%d available)\n"), rc);
 		}
-	} else if (features & LIRC_CAN_SEND_LIRCCODE) {
+		can_send = true;
+	}
+	if (features & LIRC_CAN_SEND_LIRCCODE) {
 		printf(_(" - Device can send using device dependent LIRCCODE mode (not supported)\n"));
-	} else {
-		printf(_(" - Device cannot send\n"));
+		can_send = true;
 	}
+
+	if (!can_send)
+		printf(_(" - Device cannot send\n"));
 }
 
 static int lirc_send(struct arguments *args, int fd, unsigned features, struct file *f)
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/5] ir-ctl: use lirc scancode sending
  2017-09-26 20:23 [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR Sean Young
  2017-09-26 20:23 ` [PATCH 2/5] ir-ctl: show scancode lirc features Sean Young
@ 2017-09-26 20:23 ` Sean Young
  2017-09-26 20:23 ` [PATCH 4/5] ir-ctl: implement scancode reading Sean Young
  2017-09-26 20:23 ` [PATCH 5/5] keytable: show lirc device and make test show lirc scancodes Sean Young
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Young @ 2017-09-26 20:23 UTC (permalink / raw)
  To: linux-media

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/ir-ctl.c | 79 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 52 insertions(+), 27 deletions(-)

diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index 32d7162f..f0dcd2a3 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -66,9 +66,18 @@ const char *argp_program_bug_address = "Sean Young <sean@mess.org>";
 struct file {
 	struct file *next;
 	const char *fname;
-	unsigned carrier;
-	unsigned len;
-	unsigned buf[LIRCBUF_SIZE];
+	bool is_scancode;
+	union {
+		struct {
+			unsigned carrier;
+			unsigned len;
+			unsigned buf[LIRCBUF_SIZE];
+		};
+		struct {
+			unsigned scancode;
+			unsigned protocol;
+		};
+	};
 };
 
 struct arguments {
@@ -187,7 +196,7 @@ static unsigned parse_emitters(char *p)
 
 static struct file *read_file(const char *fname)
 {
-	bool expect_pulse = true, seen_scancode = false;
+	bool expect_pulse = true;
 	int lineno = 0, lastspace = 0;
 	char line[1024];
 	int len = 0;
@@ -206,6 +215,7 @@ static struct file *read_file(const char *fname)
 		fprintf(stderr, _("Failed to allocate memory\n"));
 		return NULL;
 	}
+	f->is_scancode = false;
 	f->carrier = 0;
 	f->fname = fname;
 
@@ -226,7 +236,7 @@ static struct file *read_file(const char *fname)
 
 		if (strcmp(keyword, "scancode") == 0) {
 			enum rc_proto proto;
-			unsigned scancode, carrier;
+			unsigned scancode;
 			char *scancodestr;
 
 			if (len) {
@@ -257,19 +267,9 @@ static struct file *read_file(const char *fname)
 				return NULL;
 			}
 
-			if (len + protocol_max_size(proto) >= LIRCBUF_SIZE) {
-				fprintf(stderr, _("error: %s:%d: too much IR for one transmit\n"), fname, lineno);
-				return NULL;
-			}
-
-			carrier = protocol_carrier(proto);
-			if (f->carrier && f->carrier != carrier)
-				fprintf(stderr, _("error: %s:%d: carrier already specified\n"), fname, lineno);
-			else
-				f->carrier = carrier;
-
-			len += protocol_encode(proto, scancode, f->buf);
-			seen_scancode = true;
+			f->is_scancode = true;
+			f->scancode = scancode;
+			f->protocol = proto;
 			continue;
 		}
 
@@ -285,7 +285,7 @@ static struct file *read_file(const char *fname)
 			continue;
 		}
 
-		if (seen_scancode) {
+		if (f->is_scancode) {
 			fprintf(stderr, _("error: %s:%d: scancode must be appear in file by itself\n"), fname, lineno);
 			return NULL;
 		}
@@ -383,9 +383,9 @@ static struct file *read_scancode(const char *name)
 		return NULL;
 	}
 
-	f->carrier = protocol_carrier(proto);
-	f->fname = name;
-	f->len = protocol_encode(proto, scancode, f->buf);
+	f->is_scancode = true;
+	f->scancode = scancode;
+	f->protocol = proto;
 
 	return f;
 }
@@ -772,16 +772,41 @@ static void lirc_features(struct arguments *args, int fd, unsigned features)
 static int lirc_send(struct arguments *args, int fd, unsigned features, struct file *f)
 {
 	const char *dev = args->device;
-	int mode = LIRC_MODE_PULSE;
+	int rc, mode;
+	ssize_t ret;
+
+	if (f->is_scancode && (features & LIRC_CAN_SEND_SCANCODE)) {
+		mode = LIRC_MODE_SCANCODE;
+		rc = ioctl(fd, LIRC_SET_SEND_MODE, &mode);
+		if (rc == 0) {
+			struct lirc_scancode sc = {
+				.scancode = f->scancode,
+				.rc_proto = f->protocol,
+				.flags = 0
+			};
+			ret = TEMP_FAILURE_RETRY(write(fd, &sc, sizeof sc));
+			if (ret > 0)
+				return 0;
+		}
+	}
 
 	if (!(features & LIRC_CAN_SEND_PULSE)) {
 		fprintf(stderr, _("%s: device cannot send raw ir\n"), dev);
 		return EX_UNAVAILABLE;
 	}
 
-	if (ioctl(fd, LIRC_SET_SEND_MODE, &mode)) {
-		fprintf(stderr, _("%s: failed to set send mode: %m\n"), dev);
-		return EX_IOERR;
+	mode = LIRC_MODE_PULSE;
+	rc = ioctl(fd, LIRC_SET_SEND_MODE, &mode);
+	if (rc) {
+		fprintf(stderr, _("%s: cannot set send mode\n"), dev);
+		return EX_UNAVAILABLE;
+	}
+
+	if (f->is_scancode) {
+		// encode scancode
+		enum rc_proto proto = f->protocol;
+		f->len = protocol_encode(f->protocol, f->scancode, f->buf);
+		f->carrier = protocol_carrier(proto);
 	}
 
 	if (args->carrier && f->carrier)
@@ -796,7 +821,7 @@ static int lirc_send(struct arguments *args, int fd, unsigned features, struct f
 		for (i=0; i<f->len; i++)
 			printf("%s %u\n", i & 1 ? "space" : "pulse", f->buf[i]);
 	}
-	ssize_t ret = TEMP_FAILURE_RETRY(write(fd, f->buf, size));
+	ret = TEMP_FAILURE_RETRY(write(fd, f->buf, size));
 	if (ret < 0) {
 		fprintf(stderr, _("%s: failed to send: %m\n"), dev);
 		return EX_IOERR;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/5] ir-ctl: implement scancode reading
  2017-09-26 20:23 [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR Sean Young
  2017-09-26 20:23 ` [PATCH 2/5] ir-ctl: show scancode lirc features Sean Young
  2017-09-26 20:23 ` [PATCH 3/5] ir-ctl: use lirc scancode sending Sean Young
@ 2017-09-26 20:23 ` Sean Young
  2017-09-26 20:23 ` [PATCH 5/5] keytable: show lirc device and make test show lirc scancodes Sean Young
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Young @ 2017-09-26 20:23 UTC (permalink / raw)
  To: linux-media

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/ir-ctl/ir-ctl.c    | 188 +++++++++++++++++++++++++++++++++--------------
 utils/ir-ctl/ir-encode.c |   4 +
 2 files changed, 135 insertions(+), 57 deletions(-)

diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c
index f0dcd2a3..f9cf30a3 100644
--- a/utils/ir-ctl/ir-ctl.c
+++ b/utils/ir-ctl/ir-ctl.c
@@ -24,6 +24,7 @@
 #include <fcntl.h>
 #include <argp.h>
 #include <sysexits.h>
+#include <poll.h>
 
 #include <config.h>
 
@@ -840,24 +841,122 @@ static int lirc_send(struct arguments *args, int fd, unsigned features, struct f
 	return 0;
 }
 
-int lirc_record(struct arguments *args, int fd, unsigned features)
+static bool keep_reading = true;
+static bool leading_space = true;
+
+int lirc_record_mode2(FILE *out, int fd, struct arguments *args)
 {
-	char *dev = args->device;
-	FILE *out = stdout;
-	int rc = EX_IOERR;
 	int mode = LIRC_MODE_MODE2;
+	unsigned buf[LIRCBUF_SIZE];
+	char *dev = args->device;
+	ssize_t ret;
 
-	if (!(features & LIRC_CAN_REC_MODE2)) {
-		fprintf(stderr, _("%s: device cannot record raw ir\n"), dev);
-		return EX_UNAVAILABLE;
+	// some kernel versions return errors, ignore them
+	ioctl(fd, LIRC_SET_REC_MODE, &mode);
+
+	ret = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
+	if (ret < 0) {
+		fprintf(stderr, _("%s: failed read: %m\n"), dev);
+		return EX_IOERR;
 	}
 
-	// kernel v4.8 and v4.9 return ENOTTY
-	if (ioctl(fd, LIRC_SET_REC_MODE, &mode) && errno != ENOTTY) {
-		fprintf(stderr, _("%s: failed to set record mode: %m\n"), dev);
+	if (ret == 0 || ret % sizeof(unsigned)) {
+		fprintf(stderr, _("%s: read returned %zd bytes\n"), dev, ret);
+		return EX_IOERR;
+	}
+
+	for (int i=0; i<ret / sizeof(unsigned); i++) {
+		unsigned val = buf[i] & LIRC_VALUE_MASK;
+		unsigned msg = buf[i] & LIRC_MODE2_MASK;
+
+		// FIXME: the kernel often send us a space after
+		// the IR receiver comes out of idle mode. This
+		// is meaningless, maybe fix the kernel?
+		if (leading_space && msg == LIRC_MODE2_SPACE)
+			continue;
+		else
+			leading_space = false;
+
+		if (args->oneshot &&
+			(msg == LIRC_MODE2_TIMEOUT ||
+			(msg == LIRC_MODE2_SPACE && val > 19000))) {
+			keep_reading = false;
+			break;
+		}
+
+		switch (msg) {
+		case LIRC_MODE2_TIMEOUT:
+			fprintf(out, "timeout %u\n", val);
+			leading_space = true;
+			break;
+		case LIRC_MODE2_PULSE:
+			fprintf(out, "pulse %u\n", val);
+			break;
+		case LIRC_MODE2_SPACE:
+			fprintf(out, "space %u\n", val);
+			break;
+		case LIRC_MODE2_FREQUENCY:
+			fprintf(out, "carrier %u\n", val);
+			break;
+		}
+
+		fflush(out);
+	}
+
+	return 0;
+}
+
+int lirc_record_scancode(FILE *out, int fd, const char *dev)
+{
+	struct lirc_scancode sc[32];
+	int mode = LIRC_MODE_SCANCODE;
+	ssize_t ret;
+
+	ret = ioctl(fd, LIRC_SET_REC_MODE, &mode);
+	if (ret < 0) {
+		fprintf(stderr, _("%s: failed set recording mode: %m\n"), dev);
+		return EX_IOERR;
+	}
+
+	ret = TEMP_FAILURE_RETRY(read(fd, sc, sizeof sc));
+	if (ret < 0) {
+		fprintf(stderr, _("%s: failed read: %m\n"), dev);
 		return EX_IOERR;
 	}
 
+	if (ret == 0 || ret % sizeof sc[0]) {
+		fprintf(stderr, _("%s: read returned %zd bytes\n"), dev, ret);
+		return EX_IOERR;
+	}
+
+	for (int i=0; i<ret / sizeof sc[0]; i++) {
+		const char *proto = protocol_name(sc[i].rc_proto);
+
+		if (proto)
+			fprintf(out, "scancode %s:0x%llx\n",
+				protocol_name(sc[i].rc_proto), sc[i].scancode);
+		else
+			fprintf(out, "scancode protocol-%u:0x%llx\n", i,
+				sc[i].scancode);
+	}
+
+	fflush(out);
+
+	return 0;
+}
+
+int lirc_record(struct arguments *args, int fd, unsigned features)
+{
+	char *dev = args->device;
+	FILE *out = stdout;
+	int rc = 0;
+	ssize_t ret;
+
+	if (!(features & (LIRC_CAN_REC_MODE2 | LIRC_CAN_REC_SCANCODE))) {
+		fprintf(stderr, _("%s: device cannot receive\n"), dev);
+		return EX_UNAVAILABLE;
+	}
+
 	if (args->savetofile) {
 		out = fopen(args->savetofile, "w");
 		if (!out) {
@@ -865,65 +964,40 @@ int lirc_record(struct arguments *args, int fd, unsigned features)
 			return EX_CANTCREAT;
 		}
 	}
-	unsigned buf[LIRCBUF_SIZE];
-
-	bool keep_reading = true;
-	bool leading_space = true;
 
 	while (keep_reading) {
-		ssize_t ret = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
-		if (ret < 0) {
-			fprintf(stderr, _("%s: failed read: %m\n"), dev);
-			goto err;
-		}
-
-		if (ret == 0 || ret % sizeof(unsigned)) {
-			fprintf(stderr, _("%s: read returned %zd bytes\n"),
-								dev, ret);
-			goto err;
+		if (features & LIRC_CAN_REC_SCANCODE) {
+			unsigned mode = LIRC_MODE_MODE2 | LIRC_MODE_SCANCODE;
+			if (ioctl(fd, LIRC_SET_POLL_MODE, &mode)) {
+				fprintf(stderr, _("%s: set poll mode failed: %m\n"), dev);
+				rc = EX_IOERR;
+				break;
+			}
 		}
 
-		for (int i=0; i<ret / sizeof(unsigned); i++) {
-			unsigned val = buf[i] & LIRC_VALUE_MASK;
-			unsigned msg = buf[i] & LIRC_MODE2_MASK;
-
-			// FIXME: the kernel often send us a space after
-			// the IR receiver comes out of idle mode. This
-			// is meaningless, maybe fix the kernel?
-			if (leading_space && msg == LIRC_MODE2_SPACE)
+		struct pollfd p = { .fd = fd, .events = POLLIN };
+		ret = poll(&p, 1, -1);
+		if (ret == -1) {
+			if (errno == -EINTR)
 				continue;
-			else
-				leading_space = false;
+			fprintf(stderr, _("%s: poll failed: %m\n"), dev);
+			rc = EX_IOERR;
+			break;
+		}
 
-			if (args->oneshot &&
-				(msg == LIRC_MODE2_TIMEOUT ||
-				(msg == LIRC_MODE2_SPACE && val > 19000))) {
-				keep_reading = false;
+		if (features & LIRC_CAN_REC_SCANCODE) {
+			rc = lirc_record_scancode(out, fd, dev);
+			if (rc)
 				break;
-			}
+		}
 
-			switch (msg) {
-			case LIRC_MODE2_TIMEOUT:
-				fprintf(out, "timeout %u\n", val);
-				leading_space = true;
-				break;
-			case LIRC_MODE2_PULSE:
-				fprintf(out, "pulse %u\n", val);
-				break;
-			case LIRC_MODE2_SPACE:
-				fprintf(out, "space %u\n", val);
-				break;
-			case LIRC_MODE2_FREQUENCY:
-				fprintf(out, "carrier %u\n", val);
+		if (features & LIRC_CAN_REC_MODE2) {
+			rc = lirc_record_mode2(out, fd, args);
+			if (rc)
 				break;
-			}
-
-			fflush(out);
 		}
 	}
 
-	rc = 0;
-err:
 	if (args->savetofile)
 		fclose(out);
 
diff --git a/utils/ir-ctl/ir-encode.c b/utils/ir-ctl/ir-encode.c
index 8a125628..702c1bb0 100644
--- a/utils/ir-ctl/ir-encode.c
+++ b/utils/ir-ctl/ir-encode.c
@@ -18,6 +18,7 @@
  */
 
 #include <stdbool.h>
+#include <stdlib.h>
 #include <stdint.h>
 #include <ctype.h>
 
@@ -445,5 +446,8 @@ unsigned protocol_encode(enum rc_proto proto, unsigned scancode, unsigned *buf)
 
 const char* protocol_name(enum rc_proto proto)
 {
+	if (proto >= ARRAY_SIZE(encoders))
+		return NULL;
+
 	return encoders[proto].name;
 }
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 5/5] keytable: show lirc device and make test show lirc scancodes
  2017-09-26 20:23 [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR Sean Young
                   ` (2 preceding siblings ...)
  2017-09-26 20:23 ` [PATCH 4/5] ir-ctl: implement scancode reading Sean Young
@ 2017-09-26 20:23 ` Sean Young
  3 siblings, 0 replies; 5+ messages in thread
From: Sean Young @ 2017-09-26 20:23 UTC (permalink / raw)
  To: linux-media

Now you can see what protocol any remote is using the following command.

$ ir-keytable -c -p all -t
Old keytable cleared
Protocols changed to lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp
Testing events. Please, press CTRL-C to abort.
2124.576099: lirc protocol(rc5): scancode = 0x1e11
2124.576143: event type EV_MSC(0x04): scancode = 0x1e11
2124.576143: event type EV_SYN(0x00).
2125.601002: lirc protocol(rc6_mce): scancode = 0x800f0410
2125.601051: event type EV_MSC(0x04): scancode = 0x800f0410
2125.601051: event type EV_SYN(0x00).

Signed-off-by: Sean Young <sean@mess.org>
---
 utils/keytable/keytable.c | 140 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 134 insertions(+), 6 deletions(-)

diff --git a/utils/keytable/keytable.c b/utils/keytable/keytable.c
index 5d12ec31..f0744c6a 100644
--- a/utils/keytable/keytable.c
+++ b/utils/keytable/keytable.c
@@ -18,13 +18,16 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <poll.h>
 #include <stdlib.h>
 #include <string.h>
 #include <linux/input.h>
+#include <linux/lirc.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <argp.h>
+#include <time.h>
 #include <stdbool.h>
 
 #include "parse.h"
@@ -270,6 +273,7 @@ static int sysfs = 0;
 struct rc_device {
 	char *sysfs_name;	/* Device sysfs node name */
 	char *input_name;	/* Input device file name */
+	char *lirc_name;	/* Lirc device file name */
 	char *drv_name;		/* Kernel driver that implements it */
 	char *keytable_name;	/* Keycode table name */
 
@@ -1016,15 +1020,33 @@ static int v2_set_protocols(struct rc_device *rc_dev)
 static int get_attribs(struct rc_device *rc_dev, char *sysfs_name)
 {
 	struct uevents  *uevent;
-	char		*input = "input", *event = "event";
+	char		*input = "input", *event = "event", *lirc = "lirc";
 	char		*DEV = "/dev/";
-	static struct sysfs_names *input_names, *event_names, *attribs, *cur;
+	static struct sysfs_names *input_names, *event_names, *attribs, *cur, *lirc_names;
 
 	/* Clean the attributes */
 	memset(rc_dev, 0, sizeof(*rc_dev));
 
 	rc_dev->sysfs_name = sysfs_name;
 
+	lirc_names = seek_sysfs_dir(rc_dev->sysfs_name, lirc);
+	if (lirc_names) {
+		uevent = read_sysfs_uevents(lirc_names->name);
+		free_names(lirc_names);
+		if (uevent) {
+			while (uevent->next) {
+				if (!strcmp(uevent->key, "DEVNAME")) {
+					rc_dev->lirc_name = malloc(strlen(uevent->value) + strlen(DEV) + 1);
+					strcpy(rc_dev->lirc_name, DEV);
+					strcat(rc_dev->lirc_name, uevent->value);
+					break;
+				}
+				uevent = uevent->next;
+			}
+			free_uevent(uevent);
+		}
+	}
+
 	input_names = seek_sysfs_dir(rc_dev->sysfs_name, input);
 	if (!input_names)
 		return EINVAL;
@@ -1262,16 +1284,119 @@ static char *get_event_name(struct parse_event *event, u_int16_t code)
 	return "";
 }
 
-static void test_event(int fd)
+static void print_scancodes(const struct lirc_scancode *scancodes, unsigned count)
+{
+	unsigned i;
+
+	for (i=0; i< count; i++)  {
+		const char *p;
+		switch (scancodes[i].rc_proto) {
+			case RC_PROTO_UNKNOWN: p = "unknown"; break;
+			case RC_PROTO_OTHER: p = "other"; break;
+			case RC_PROTO_RC5: p = "rc5"; break;
+			case RC_PROTO_RC5X_20: p = "rc5x_20"; break;
+			case RC_PROTO_RC5_SZ: p = "rc5_sz"; break;
+			case RC_PROTO_JVC: p = "jvc"; break;
+			case RC_PROTO_SONY12: p = "sony12"; break;
+			case RC_PROTO_SONY15: p = "sony15"; break;
+			case RC_PROTO_SONY20: p = "sony20"; break;
+			case RC_PROTO_NEC: p = "nec"; break;
+			case RC_PROTO_NECX: p = "necx"; break;
+			case RC_PROTO_NEC32: p = "nec32"; break;
+			case RC_PROTO_SANYO: p = "sanyo"; break;
+			case RC_PROTO_MCIR2_KBD: p = "mcir2_kbd"; break;
+			case RC_PROTO_MCIR2_MSE: p = "mcri2_mse"; break;
+			case RC_PROTO_RC6_0: p = "rc6_0"; break;
+			case RC_PROTO_RC6_6A_20: p = "rc6_6a_20"; break;
+			case RC_PROTO_RC6_6A_24: p = "rc6_6a_24"; break;
+			case RC_PROTO_RC6_6A_32: p = "rc6_6a_32"; break;
+			case RC_PROTO_RC6_MCE: p = "rc6_mce"; break;
+			case RC_PROTO_SHARP: p = "sharp"; break;
+			case RC_PROTO_XMP: p = "xmp"; break;
+			case RC_PROTO_CEC: p = "cec"; break;
+			default: p = NULL; break;
+		}
+		printf(_("%llu.%06llu: "),
+			scancodes[i].timestamp / 1000000000ull,
+			(scancodes[i].timestamp % 1000000000ull) / 1000ull);
+
+		if (p)
+			printf(_("lirc protocol(%s): scancode = 0x%llx"),
+				p, scancodes[i].scancode);
+		else
+			printf(_("lirc protocol(%d): scancode = 0x%llx"),
+				scancodes[i].rc_proto, scancodes[i].scancode);
+
+		if (scancodes[i].flags & LIRC_SCANCODE_FLAG_REPEAT)
+			printf(_(" repeat"));
+		if (scancodes[i].flags & LIRC_SCANCODE_FLAG_TOGGLE)
+			printf(_(" toggle=1"));
+
+		printf("\n");
+	}
+}
+
+static void test_event(struct rc_device *rc_dev, int fd)
 {
 	struct input_event ev[64];
-	int rd, i;
+	struct lirc_scancode sc[64];
+	int rd, i, lircfd = -1;
+
+	if (rc_dev->lirc_name) {
+		lircfd = open(rc_dev->lirc_name, O_RDONLY | O_NONBLOCK);
+		if (lircfd == -1) {
+			perror(_("Can't open lirc device"));
+			return;
+		}
+		unsigned features;
+		if (ioctl(lircfd, LIRC_GET_FEATURES, &features)) {
+			perror(_("Can't get lirc features"));
+			return;
+		}
+
+		if (!(features & LIRC_CAN_REC_SCANCODE)) {
+			close(lircfd);
+			lircfd = -1;
+		}
+		else {
+			unsigned mode = LIRC_MODE_SCANCODE;
+			if (ioctl(lircfd, LIRC_SET_REC_MODE, &mode)) {
+				perror(_("Can't set lirc mode"));
+				return;
+			}
+
+			mode = CLOCK_MONOTONIC;
+			ioctl(fd, EVIOCSCLOCKID, &mode);
+		}
+	}
+
 
 	printf (_("Testing events. Please, press CTRL-C to abort.\n"));
 	while (1) {
+		struct pollfd pollstruct[2] = {
+			{ .fd = fd, .events = POLLIN },
+			{ .fd = lircfd, .events = POLLIN },
+		};
+
+		poll(pollstruct, lircfd != -1 ? 2 : 1, -1);
+
+		if (lircfd != -1) {
+			rd = read(lircfd, sc, sizeof(sc));
+
+			if (rd != -1) {
+				print_scancodes(sc, rd / sizeof(struct lirc_scancode));
+			} else if (errno != EAGAIN) {
+				perror(_("Error reading lirc scancode"));
+				return;
+			}
+		}
+
 		rd = read(fd, ev, sizeof(ev));
 
 		if (rd < (int) sizeof(struct input_event)) {
+			if (errno == EAGAIN)
+				continue;
+
 			perror(_("Error reading event"));
 			return;
 		}
@@ -1455,6 +1580,9 @@ static int show_sysfs_attribs(struct rc_device *rc_dev, char *name)
 			fprintf(stderr, _("\tDriver %s, table %s\n"),
 				rc_dev->drv_name,
 				rc_dev->keytable_name);
+			if (rc_dev->lirc_name)
+				fprintf(stderr, _("\tLirc device: %s\n"),
+					rc_dev->lirc_name);
 			fprintf(stderr, _("\tSupported protocols: "));
 			write_sysfs_protocols(rc_dev->supported, stderr, "%s ");
 			fprintf(stderr, "\n\t");
@@ -1585,7 +1713,7 @@ int main(int argc, char *argv[])
 
 	if (debug)
 		fprintf(stderr, _("Opening %s\n"), devicename);
-	fd = open(devicename, O_RDONLY);
+	fd = open(devicename, O_RDONLY | O_NONBLOCK);
 	if (fd < 0) {
 		perror(devicename);
 		return -1;
@@ -1644,7 +1772,7 @@ int main(int argc, char *argv[])
 	}
 
 	if (test)
-		test_event(fd);
+		test_event(&rc_dev, fd);
 
 	return 0;
 }
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-09-26 20:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-26 20:23 [PATCH 1/5] ir-ctl: a pulse space file cannot contain scancode and raw IR Sean Young
2017-09-26 20:23 ` [PATCH 2/5] ir-ctl: show scancode lirc features Sean Young
2017-09-26 20:23 ` [PATCH 3/5] ir-ctl: use lirc scancode sending Sean Young
2017-09-26 20:23 ` [PATCH 4/5] ir-ctl: implement scancode reading Sean Young
2017-09-26 20:23 ` [PATCH 5/5] keytable: show lirc device and make test show lirc scancodes Sean Young

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.