Provide simple tools for displaying raw IR and received scancodes, and sending them. Todo: - ir-rec cannot enable protocol decoders - ir-send should accept scancode on commandline - long options Signed-off-by: Sean Young <sean@xxxxxxxx> --- configure.ac | 3 + utils/Makefile.am | 1 + utils/ir/.gitignore | 4 + utils/ir/Makefile.am | 6 + utils/ir/ir-rec.1.in | 68 +++++++++++ utils/ir/ir-rec.c | 224 ++++++++++++++++++++++++++++++++++ utils/ir/ir-send.1.in | 48 ++++++++ utils/ir/ir-send.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++ utils/ir/lirc.h | 163 +++++++++++++++++++++++++ v4l-utils.spec.in | 8 +- 10 files changed, 852 insertions(+), 2 deletions(-) create mode 100644 utils/ir/.gitignore create mode 100644 utils/ir/Makefile.am create mode 100644 utils/ir/ir-rec.1.in create mode 100644 utils/ir/ir-rec.c create mode 100644 utils/ir/ir-send.1.in create mode 100644 utils/ir/ir-send.c create mode 100644 utils/ir/lirc.h diff --git a/configure.ac b/configure.ac index de54d63..d941f33 100644 --- a/configure.ac +++ b/configure.ac @@ -23,6 +23,7 @@ AC_CONFIG_FILES([Makefile utils/libmedia_dev/Makefile utils/decode_tm6000/Makefile utils/dvb/Makefile + utils/ir/Makefile utils/keytable/Makefile utils/media-ctl/Makefile utils/rds/Makefile @@ -53,6 +54,8 @@ AC_CONFIG_FILES([Makefile utils/qv4l2/qv4l2.1 utils/v4l2-compliance/v4l2-compliance.1 + utils/ir/ir-rec.1 + utils/ir/ir-send.1 utils/keytable/ir-keytable.1 utils/dvb/dvb-fe-tool.1 utils/dvb/dvbv5-scan.1 diff --git a/utils/Makefile.am b/utils/Makefile.am index 31b2979..f46b87b 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -3,6 +3,7 @@ SUBDIRS = \ libv4l2util \ libmedia_dev \ decode_tm6000 \ + ir \ keytable \ media-ctl \ v4l2-compliance \ diff --git a/utils/ir/.gitignore b/utils/ir/.gitignore new file mode 100644 index 0000000..bdecfc2 --- /dev/null +++ b/utils/ir/.gitignore @@ -0,0 +1,4 @@ +ir-rec +ir-rec.1 +ir-send +ir-send.1 diff --git a/utils/ir/Makefile.am b/utils/ir/Makefile.am new file mode 100644 index 0000000..771f197 --- /dev/null +++ b/utils/ir/Makefile.am @@ -0,0 +1,6 @@ +bin_PROGRAMS = ir-rec ir-send +man_MANS = ir-rec.1 ir-send.1 + +ir_rec_SOURCES = ir-rec.c +ir_send_SOURCES = ir-send.c + diff --git a/utils/ir/ir-rec.1.in b/utils/ir/ir-rec.1.in new file mode 100644 index 0000000..36d1472 --- /dev/null +++ b/utils/ir/ir-rec.1.in @@ -0,0 +1,68 @@ +.TH "IR\-REC" "1" "Mon Mar 16 2015" "v4l-utils @PACKAGE_VERSION@" "User Commands" +.SH NAME +ir\-rec \- shows infrared signals +.SH SYNOPSIS +.B ir\-rec +[\fIOPTION\fR]... +.SH DESCRIPTION +ir\-rec is a tool that shows infrared (IR) signals directly from the lirc +device on stdout. +.PP +.SH OPTIONS +.TP +\fB\-d\fR \fIDEV\fR +lirc device, /dev/lirc0 by default. +.TP +\fB\-c\fR +Enable carrier detection if the hardware supports it. +.TP +\fB\-r\fR +Only display raw IR. +.TP +\fB\-s\fR +Only display decoded scancodes. +.TP +\fB\-f\fR \fIFILE\fR +Write the output to a file rather than stdout. +.TP +\fB\-h\fR +Prints the help message +.SH EXAMPLES +Pressing \fBplay\fR on a Hauppauge rc5 remote results in: +.PP +.nf +$ ir-rec +pulse 950 +space 850 +pulse 1750 +space 1800 +pulse 850 +space 900 +pulse 900 +space 850 +pulse 900 +space 900 +pulse 1750 +space 1750 +pulse 900 +space 900 +pulse 1750 +space 1800 +pulse 1750 +space 1750 +pulse 900 +scancode rc5 7733 +.fi +.SH EXIT STATUS +On success, it returns 0. Otherwise, it will return the error code. +.SH BUGS +Report bugs to \fBLinux Media Mailing List <linux-media@xxxxxxxxxxxxxxx>\fR +.SH SEE ALSO +\fBir-send\fR(1) +.SH AUTHOR +Copyright (C) 2015 Sean Young +.PP +License GPLv2: GNU GPL version 2+ <http://gnu.org/licenses/gpl.html>. +.br +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. diff --git a/utils/ir/ir-rec.c b/utils/ir/ir-rec.c new file mode 100644 index 0000000..5970549 --- /dev/null +++ b/utils/ir/ir-rec.c @@ -0,0 +1,224 @@ +/* + Copyright (C) 2015 Sean Young <sean@xxxxxxxx> + */ +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "lirc.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <string.h> +#include <errno.h> + +/* + TODO + - list devices and their properties including rx resolution + - wideband receiver + - receiver carrier range + - duty cycle +*/ +#define DEFAULT_DEVICE "/dev/lirc0" + +const static char *protocols[] = { + "unknown", + "other", + "rc5", + "rc5x", + "rc5sz", + "jvc", + "sony12", + "sony15", + "sony20", + "nec", + "sanyo", + "mce_kbd", + "rc6_0", + "rc6_6a_20", + "rc6_6a_24", + "rc6_6a_32", + "rc6_mce", + "sharp", + "xmp" +}; + +#define MAX_PROTOCOL (sizeof(protocols)/sizeof(protocols[0])) + +static void usage(const char *name) +{ + printf("Usage:\n" + " %s [options]\n" + "\n" + "Options:\n" + " -d device\tlirc device (" DEFAULT_DEVICE " by default)\n" + " -c\t\tEnable carrier reports\n" + " -h\t\tThis help text\n" + " -r\t\tRaw IR only\n" + " -s\t\tscancodes only\n" + " -f file\tWrite to file rather than stdout\n", name); +} + +int main(int argc, char *argv[]) +{ + char *dev = DEFAULT_DEVICE, *output = NULL; + int rc, fd, last = 0, mode; + bool carrier_report = false; + unsigned features; + unsigned buf[4096]; + bool raw = false, scancodes = false; + FILE *outfile; + + while ((rc = getopt(argc, argv, "srf:hd:c")) != -1) { + switch (rc) + { + case 'r': + raw = true; + break; + case 's': + scancodes = true; + break; + case 'f': + output = strdupa(optarg); + break; + case 'c': + carrier_report = true; + break; + case 'd': + dev = strdupa(optarg); + break; + case 'h': + usage(argv[0]); + exit(EXIT_SUCCESS); + case '?': + fprintf(stderr, "error: invalid argument -%c\n",optopt); + exit(EXIT_FAILURE); + } + } + + if (optind < argc) { + fprintf(stderr, "error: invalid argument '%s'\n", argv[optind]); + exit(EXIT_FAILURE); + } + + fd = TEMP_FAILURE_RETRY(open(dev, O_RDONLY)); + if (fd == -1) { + fprintf(stderr, "%s: error: cannot open: %m\n", dev); + exit(EXIT_FAILURE); + } + + rc = ioctl(fd, LIRC_GET_FEATURES, &features); + if (rc) { + fprintf(stderr, "%s: error: failed to get features: %m\n", dev); + exit(EXIT_FAILURE); + } + + if (raw && !(features & LIRC_CAN_REC_MODE2)) { + fprintf(stderr, "%s: error: device does not support raw mode\n", + dev); + exit(EXIT_FAILURE); + } + + if (scancodes && !(features & LIRC_CAN_REC_SCANCODE)) { + fprintf(stderr, "%s: error: device does not support key code\n", + dev); + exit(EXIT_FAILURE); + } + + if (!(features & LIRC_CAN_MEASURE_CARRIER)) { + if (carrier_report) + fprintf(stderr, "%s: warning: cannot measure carrier\n", + dev); + } else { + rc = ioctl(fd, LIRC_SET_MEASURE_CARRIER_MODE, &carrier_report); + if (rc) + fprintf(stderr, "%s: warning: failed to set " + "measure carrier: %m\n", dev); + } + + mode = LIRC_REC2MODE(LIRC_CAN_REC(features)); + if (!raw && scancodes) + mode &= ~LIRC_MODE_MODE2; + if (!scancodes && raw) + mode &= ~LIRC_MODE_SCANCODE; + + /* + * Note that kernels that do not support LIRC_CAN_REC_SCANCODE also + * ignore LIRC_SET_REC_MODE + */ + rc = ioctl(fd, LIRC_SET_REC_MODE, &mode); + if (rc) { + fprintf(stderr, "%s: warning: failed to set record mode: %m\n", + dev); + exit(EXIT_FAILURE); + } + + if (output) { + outfile = fopen(output, "w"); + if (!outfile) { + fprintf(stderr, "%s: error: failed to open: %m\n", + output); + exit(EXIT_FAILURE); + } + } else { + outfile = stdout; + } + + do { + int i; + + rc = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))); + if (rc == -1) { + fprintf(stderr, "%s: error: failed to read: %m\n", dev); + exit(EXIT_FAILURE); + } + + if (rc % sizeof(unsigned)) { + fprintf(stderr, "%s: error: unexpected return value\n", dev); + break; + } + + for (i=0; i<rc/sizeof(unsigned); i++) { + if (last) { + fprintf(outfile, " %u %s\n", buf[i], + last & LIRC_SCANCODE_TOGGLE ? "toggle" : + last & LIRC_SCANCODE_REPEAT ? "repeat" : + "" ); + last = 0; + continue; + } + fflush(outfile); + unsigned val = buf[i] & LIRC_VALUE_MASK; + switch (buf[i] & LIRC_MODE2_MASK) { + case LIRC_MODE2_PULSE: + fprintf(outfile, "pulse %u\n", val); + break; + case LIRC_MODE2_SPACE: + fprintf(outfile, "space %u\n", val); + break; + case LIRC_MODE2_FREQUENCY: + fprintf(outfile, "carrier %u\n", val); + break; + case LIRC_MODE2_TIMEOUT: + fprintf(outfile, "timeout %u\n", val); + break; + case LIRC_MODE2_SCANCODE: + last = buf[i]; + val = buf[i] & LIRC_SCANCODE_PROTOCOL_MASK; + if (val >= MAX_PROTOCOL) + fprintf(outfile, "scancode %u", val); + else + fprintf(outfile, "scancode %s", + protocols[val]); + break; + } + } + } + while (rc > 0); + + close(fd); + fclose(outfile); + + return 0; +} diff --git a/utils/ir/ir-send.1.in b/utils/ir/ir-send.1.in new file mode 100644 index 0000000..8bbcdb3 --- /dev/null +++ b/utils/ir/ir-send.1.in @@ -0,0 +1,48 @@ +.TH "IR\-SEND" "1" "Mon Mar 16 2015" "v4l-utils @PACKAGE_VERSION@" "User Commands" +.SH NAME +ir\-send \- emit infrared signals +.SH SYNOPSIS +.B ir\-send +[\fIOPTION\fR]...\fIFILE\fR +.SH DESCRIPTION +ir\-send is a tool that emits (or "blasts") infrared (IR) signals, listed in +FILE. +.PP +.SH OPTIONS +.TP +\fB\-d\fR \fIDEV\fR +lirc device, /dev/lirc0 by default. +.TP +\fB\-c\fR \fIcarrier\fR +Set the carrier if the hardware supports it. +.TP +\fB-t\fR \fIemitter[,emitter]...\fR +A comma seperated list of physical emitters used on the hardware. +.TP +\fB\-h\fR +Prints the help message +.PP +Any line starting with # is considered a comment and ignored. Either the +IR is encoded raw IR, with alternating pulse/space lines following by a +duration in nanoseconds. +.PP +The alternative is a scancode in a particular protocol, where the format +is "scancode PROTO SCANCODE [repeat] [toggle]". Proto is one of: \fBunknown\fR, +\fBother\fR, \fB rc5\fR, \fB rc5x\fR, \fB rc5sz\fR, \fB jvc\fR, \fB sony12\fR, \fB sony15\fR, \fB sony20\fR, \fB nec\fR, \fB sanyo\fR, \fB mce_kbd\fR, \fB +rc6_0\fR, \fB rc6_6a_20\fR, \fB rc6_6a_24\fR, \fB rc6_6a_32\fR, \fB rc6_mce\fR, \fB sharp\fR, \fB xmp\fR. +Add \fBrepeat\fR for nec repeats or \fBtoggle\fR for rc5/r6 protocols, if desired. +.SH EXAMPLES +\fBscancode nec 43031\fR +.SH EXIT STATUS +On success, it returns 0. Otherwise, it will return the error code. +.SH BUGS +Report bugs to \fBLinux Media Mailing List <linux-media@xxxxxxxxxxxxxxx>\fR +.SH SEE ALSO +\fBir-rec\fR(1) +.SH AUTHOR +Copyright (C) 2015 Sean Young +.PP +License GPLv2: GNU GPL version 2+ <http://gnu.org/licenses/gpl.html>. +.br +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. diff --git a/utils/ir/ir-send.c b/utils/ir/ir-send.c new file mode 100644 index 0000000..34401f5 --- /dev/null +++ b/utils/ir/ir-send.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2015 Sean Young <sean@xxxxxxxx> + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <ctype.h> +#include <getopt.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "lirc.h" + +static char *dev = "/dev/lirc0"; +#define LIRCBUF_SIZE 256 +static int line; +static char *irdata; + +const static char *protocols[] = { + "unknown", + "other", + "rc5", + "rc5x", + "rc5sz", + "jvc", + "sony12", + "sony15", + "sony20", + "nec", + "sanyo", + "mce_kbd", + "rc6_0", + "rc6_6a_20", + "rc6_6a_24", + "rc6_6a_32", + "rc6_mce", + "sharp", + "xmp", + NULL +}; + +int proto_to_int(const char *proto) +{ + int i; + char *end; + long p; + + for (i=0; protocols[i]; i++) { + if (!strcasecmp(protocols[i], proto)) + return i; + } + + p = strtol(proto, &end, 10); + + if (*end != 0 || p < 0 || p > INT_MAX) { + fprintf(stderr, "%s:%d: protocol `%s' invalid\n", irdata, + line, proto); + exit(EXIT_FAILURE); + } + + return p; +} + +static int parse_emitters(const char *str) +{ + int emitters = 0; + const char *p = str; + char *q; + + while (*p) { + long emitter; + + emitter = strtol(p, &q, 10); + if (p == q) + return -1; + + if (emitter < 1 || emitters > 32) + return -1; + + emitters |= 1 << (emitter - 1); + p = q; + while (isspace(*p)) p++; + if (*p == ',') { + p++; + continue; + } + if (*p) + return -1; + } + + return emitters == 0 ? -1 : emitters; +} + +void parse_and_send_scancode(int fd, char *str) +{ + unsigned code[2]; + long s; + char *end; + + /* scancode PROTO scancode [repeat] [toggle] */ + str += 8; + char *proto = strtok_r(str, " \t\n", &end); + char *scancode = strtok_r(NULL, " \t\n", &end); + char *option = strtok_r(NULL, " \t\n", &end); + + if (!proto) { + fprintf(stderr, "%s:%d: missing protocol\n", irdata, line); + exit(EXIT_FAILURE); + } + + if (!scancode) { + fprintf(stderr, "%s:%d: missing scancode\n", irdata, line); + exit(EXIT_FAILURE); + } + + code[0] = LIRC_MODE2_SCANCODE | proto_to_int(proto); + + s = strtol(scancode, &end, 10); + if (*end != 0 || s < 0 || s > UINT_MAX) { + fprintf(stderr, "%s:%d: scancode `%s' invalid\n", irdata, line, + scancode); + exit(EXIT_FAILURE); + } + + code[1] = s; + if (option) { + if (strcasecmp(option, "repeat") == 0) + code[0] |= LIRC_SCANCODE_REPEAT; + else if (strcasecmp(option, "toggle") == 0) + code[0] |= LIRC_SCANCODE_TOGGLE; + else if (*option != '#') { // not a comment + fprintf(stderr, "%s:%d: `%s' not expected\n", irdata, + line, option); + exit(EXIT_FAILURE); + } + } + + unsigned mode = LIRC_MODE_SCANCODE; + + if (ioctl(fd, LIRC_SET_SEND_MODE, &mode)) { + fprintf(stderr, "%s: error: failed to set scancode send mode: %m\n", dev); + exit(EXIT_FAILURE); + } + + if (write(fd, code, sizeof(code)) == -1) { + fprintf(stderr, "%s: error: failed to transmit: %m\n", dev); + exit(EXIT_FAILURE); + } +} + +void send_rawir(int fd, unsigned *codes, unsigned count) +{ + if (count == 0) + return; + + if (!(count % 2)) + count--; + + unsigned mode = LIRC_MODE_PULSE; + + if (ioctl(fd, LIRC_SET_SEND_MODE, &mode)) { + fprintf(stderr, "%s: error: failed to set raw ir send mode: %m\n", dev); + exit(EXIT_FAILURE); + } + + if (write(fd, codes, count * sizeof(unsigned)) == -1) { + fprintf(stderr, "%s: error: failed to transmit: %m\n", dev); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char *argv[]) +{ + unsigned codes[LIRCBUF_SIZE], count = 0; + char buf[1000]; + int fd, carrier = 0, rc; + bool pulse = true; + FILE *file; + unsigned features; + int emitters = 0; + + while ((rc = getopt(argc, argv, "t:d:c:h")) != -1) { + switch (rc) { + case 'd': + dev = strdup(optarg); + break; + case 'c': + carrier = atoi(optarg); + break; + case 't': + emitters = parse_emitters(optarg); + if (emitters == -1) { + fprintf(stderr, "cannot parse emitters: %s\n", optarg); + exit(EXIT_SUCCESS); + } + case 'h': + printf("Usage: %s [-d device] [-c carrier] [-t transmitters] file\n", argv[0]); + exit(EXIT_SUCCESS); + case '?': + fprintf(stderr, "error: invalid argument -%c\n", optopt); + exit(EXIT_FAILURE); + } + } + + if (optind >= argc) { + irdata = "<stdin>"; + file = stdin; + } else { + irdata = argv[optind++]; + + if (optind < argc) { + fprintf(stderr, "error: unexpected argument `%s'\n", + argv[optind]); + exit(EXIT_FAILURE); + } + + if (strcmp(irdata, "-")) { + file = fopen(irdata, "rt"); + + if (!file) { + printf("%s: cannot open: %m\n", irdata); + exit(EXIT_FAILURE); + } + } else { + irdata = "<stdin>"; + file = stdin; + } + } + + fd = open(dev, O_WRONLY); + if (fd == -1) { + perror(dev); + exit(EXIT_FAILURE); + } + + if (ioctl(fd, LIRC_GET_FEATURES, &features)) { + fprintf(stderr, "%s: failed to get features: %m\n", dev); + exit(EXIT_FAILURE); + } + + if (!(features & LIRC_CAN_SEND_MASK)) { + fprintf(stderr, "%s: device cannot transmit\n", dev); + exit(EXIT_FAILURE); + } + + if (carrier) { + if (features & LIRC_CAN_SET_SEND_CARRIER) { + if (ioctl(fd, LIRC_SET_SEND_CARRIER, &carrier)) + fprintf(stderr, "%s: failed to set carrier: %m\n", dev); + } else + fprintf(stderr, + "%s: carrier cannot be set on device\n", dev); + } + + if (emitters) { + if (features & LIRC_CAN_SET_TRANSMITTER_MASK) { + rc = ioctl(fd, LIRC_SET_TRANSMITTER_MASK, &emitters); + if (rc < 0) + fprintf(stderr, "%s: failed to set transmitters: %m\n", dev); + if (rc > 0) + fprintf(stderr, "%s: failed to set transmitters, number of emitters %d\n", dev, rc); + + } else + fprintf(stderr, + "%s: transmitters cannot be set on device\n", dev); + } + + while (fgets(buf, sizeof(buf), file)) { + char *q = buf; + while (*q && isspace(*q)) q++; + line++; + + if (*q == '#' || !*q) continue; + + if (strncmp(q, "space", 5) == 0) { + q += 5; + while (*q && isspace(*q)) q++; + if (pulse) { + printf("%s:%d: space not expected\n", irdata, line); + } else { + codes[count++] = atoi(q); + } + pulse = true; + } else if (strncmp(q, "pulse", 5) == 0) { + if (!(features & LIRC_CAN_SEND_MODE2)) { + fprintf(stderr, "%s: device does not support raw IR transmit\n", dev); + exit(EXIT_FAILURE); + } + + q += 5; + while (*q && isspace(*q)) q++; + if (pulse == false) { + printf("%s:%d: pulse not expected\n", irdata, line); + } else { + codes[count++] = atoi(q); + } + pulse = false; + } else if (strncmp(q, "scancode", 8) == 0) { + if (!(features & LIRC_CAN_SEND_SCANCODE)) { + fprintf(stderr, "%s: device or kernel does not support scancode IR transmit\n", dev); + exit(EXIT_FAILURE); + } + send_rawir(fd, codes, count); + count = 0; + parse_and_send_scancode(fd, q); + } else { + printf("%s:%d: unexpected\n", irdata, line); + } + + if (count == LIRCBUF_SIZE) { + fprintf(stderr, "%s: ir data too long\n", irdata); + exit(EXIT_FAILURE); + } + } + + send_rawir(fd, codes, count); + fclose(file); + close(fd); + + return 0; +} diff --git a/utils/ir/lirc.h b/utils/ir/lirc.h new file mode 100644 index 0000000..3807ded --- /dev/null +++ b/utils/ir/lirc.h @@ -0,0 +1,163 @@ +/* + * lirc.h - linux infrared remote control header file + * last modified 2010/07/13 by Jarod Wilson + */ + +#ifndef _LINUX_LIRC_H +#define _LINUX_LIRC_H + +#include <linux/types.h> +#include <linux/ioctl.h> + +#define PULSE_BIT 0x01000000 +#define PULSE_MASK 0x00FFFFFF + +#define LIRC_MODE2_SPACE 0x00000000 +#define LIRC_MODE2_PULSE 0x01000000 +#define LIRC_MODE2_FREQUENCY 0x02000000 +#define LIRC_MODE2_TIMEOUT 0x03000000 +#define LIRC_MODE2_SCANCODE 0x04000000 + +#define LIRC_VALUE_MASK 0x00FFFFFF +#define LIRC_MODE2_MASK 0xFF000000 + +#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) +#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) +#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) +#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) + +#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) +#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) + +#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) +#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) +#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) +#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) +#define LIRC_IS_SCANCODE(val) (LIRC_MODE2(val) == LIRC_MODE2_SCANCODE) + +#define LIRC_SCANCODE_TOGGLE 0x00800000 +#define LIRC_SCANCODE_REPEAT 0x00400000 +#define LIRC_SCANCODE_PROTOCOL_MASK 0x000000ff + +/* used heavily by lirc userspace */ +#define lirc_t int + +/*** lirc compatible hardware features ***/ + +#define LIRC_MODE2SEND(x) (x) +#define LIRC_SEND2MODE(x) (x) +#define LIRC_MODE2REC(x) ((x) << 16) +#define LIRC_REC2MODE(x) ((x) >> 16) + +#define LIRC_MODE_RAW 0x00000001 +#define LIRC_MODE_PULSE 0x00000002 +#define LIRC_MODE_MODE2 0x00000004 +#define LIRC_MODE_SCANCODE 0x00000008 +#define LIRC_MODE_LIRCCODE 0x00000010 + + +#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) +#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) +#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) +#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) +#define LIRC_CAN_SEND_SCANCODE LIRC_MODE2SEND(LIRC_MODE_SCANCODE) + +#define LIRC_CAN_SEND_MASK 0x0000003f + +#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 +#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 +#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 + +#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) +#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) +#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) +#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) +#define LIRC_CAN_REC_SCANCODE LIRC_MODE2REC(LIRC_MODE_SCANCODE) + +#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) + +#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 +#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 +#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 +#define LIRC_CAN_SET_REC_FILTER 0x08000000 +#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000 +#define LIRC_CAN_MEASURE_CARRIER 0x02000000 +#define LIRC_CAN_SET_REC_CARRIER 0x01000000 + +#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) +#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) + +/*** IOCTL commands for lirc driver ***/ + +#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) + +#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) +#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) +#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) +#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) +#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) +#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) + +#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) +#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) + +#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) +#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) +#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) +#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) + +/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ +#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) + +#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) +#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) +/* Note: these can reset the according pulse_width */ +#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) +#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) +#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) +#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) + +/* + * when a timeout != 0 is set the driver will send a + * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is + * never sent, timeout is disabled by default + */ +#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) + +/* 1 enables, 0 disables timeout reports in MODE2 */ +#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) + +/* + * pulses shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) +/* + * spaces shorter than this are filtered out by hardware (software + * emulation in lirc_dev?) + */ +#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) +/* + * if filter cannot be set independently for pulse/space, this should + * be used + */ +#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) + +/* + * if enabled from the next key press on the driver will send + * LIRC_MODE2_FREQUENCY packets + */ +#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) + +/* + * to set a range use LIRC_SET_REC_CARRIER_RANGE with the + * lower bound first and later LIRC_SET_REC_CARRIER with the upper bound + */ +#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) + +#define LIRC_SETUP_START _IO('i', 0x00000021) +#define LIRC_SETUP_END _IO('i', 0x00000022) + +#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) + +#endif diff --git a/v4l-utils.spec.in b/v4l-utils.spec.in index dd8959b..6eeca9c 100644 --- a/v4l-utils.spec.in +++ b/v4l-utils.spec.in @@ -17,8 +17,8 @@ Requires: libv4l = %{version}-%{release} %description v4l-utils is a collection of various video4linux (V4L) and DVB utilities. The -main v4l-utils package contains cx18-ctl, ir-keytable, ivtv-ctl, v4l2-ctl and -v4l2-sysfs-path. +main v4l-utils package contains cx18-ctl, ir-keytable, ir-rec, ir-send, +ivtv-ctl, v4l2-ctl and v4l2-sysfs-path. %package devel-tools @@ -129,10 +129,14 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %config(noreplace) %{_sysconfdir}/udev/rules.d/70-infrared.rules %{_bindir}/cx18-ctl %{_bindir}/ir-keytable +%{_bindir}/ir-rec +%{_bindir}/ir-send %{_bindir}/ivtv-ctl %{_bindir}/v4l2-ctl %{_bindir}/v4l2-sysfs-path %{_mandir}/man1/ir-keytable.1* +%{_mandir}/man1/ir-rec.1* +%{_mandir}/man1/ir-send.1* %files devel-tools %defattr(-,root,root,-) -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html