Some drivers like gpio-ir-tx and mceusb allow unmodulated signal to be sent by setting the carrier to 0. Likewise the timeout can be set to 0. Signed-off-by: Sean Young <sean@xxxxxxxx> --- utils/ir-ctl/ir-ctl.c | 71 +++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/utils/ir-ctl/ir-ctl.c b/utils/ir-ctl/ir-ctl.c index ba454619..abf3ccf6 100644 --- a/utils/ir-ctl/ir-ctl.c +++ b/utils/ir-ctl/ir-ctl.c @@ -59,6 +59,7 @@ /* See drivers/media/rc/lirc_dev.c line 22 */ #define LIRCBUF_SIZE 1024 #define IR_DEFAULT_TIMEOUT 125000 +#define UNSET UINT32_MAX const char *argp_program_version = "IR ctl version " V4L_UTILS_VERSION; const char *argp_program_bug_address = "Sean Young <sean@xxxxxxxx>"; @@ -158,17 +159,18 @@ static const char doc[] = N_( "Note that most lirc setting have global state, i.e. the device will remain\n" "in this state until set otherwise."); -static int strtoint(const char *p, const char *unit) +static bool strtoint(const char *p, const char *unit, unsigned *ret) { char *end; - long arg = strtol(p, &end, 10); + long arg = strtoll(p, &end, 10); if (end == NULL || (end[0] != 0 && strcasecmp(end, unit) != 0)) - return 0; + return false; - if (arg <= 0 || arg >= 0xffffff) - return 0; + if (arg < 0 || arg >= 0xffffff) + return false; - return arg; + *ret = arg; + return true; } static bool strtoscancode(const char *p, unsigned *ret) @@ -221,7 +223,7 @@ static struct send *read_file_pulse_space(struct arguments *args, const char *fn } f->is_scancode = false; f->is_keycode = false; - f->carrier = 0; + f->carrier = UNSET; f->fname = fname; while (fgets(line, sizeof(line), input)) { @@ -300,8 +302,8 @@ static struct send *read_file_pulse_space(struct arguments *args, const char *fn continue; } - int arg = strtoint(p, ""); - if (arg == 0) { + unsigned int arg; + if (!strtoint(p, "", &arg)) { fprintf(stderr, _("warning: %s:%d: invalid argument '%s'\n"), fname, lineno, p); continue; } @@ -313,6 +315,10 @@ static struct send *read_file_pulse_space(struct arguments *args, const char *fn } if (strcmp(keyword, "space") == 0) { + if (arg == 0) { + fprintf(stderr, _("warning: %s:%d: invalid argument to space '%d'\n"), fname, lineno, arg); + continue; + } if (expect_pulse) { if (len == 0) { fprintf(stderr, _("warning: %s:%d: leading space ignored\n"), @@ -326,13 +332,17 @@ static struct send *read_file_pulse_space(struct arguments *args, const char *fn lastspace = lineno; expect_pulse = true; } else if (strcmp(keyword, "pulse") == 0) { + if (arg == 0) { + fprintf(stderr, _("warning: %s:%d: invalid argument to pulse '%d'\n"), fname, lineno, arg); + continue; + } if (!expect_pulse) f->buf[len-1] += arg; else f->buf[len++] = arg; expect_pulse = false; } else if (strcmp(keyword, "carrier") == 0) { - if (f->carrier && f->carrier != arg) { + if (f->carrier != UNSET && f->carrier != arg) { fprintf(stderr, _("warning: %s:%d: carrier already specified\n"), fname, lineno); } else { f->carrier = arg; @@ -383,7 +393,7 @@ static struct send *read_file_raw(struct arguments *args, const char *fname, FIL } f->is_scancode = false; f->is_keycode = false; - f->carrier = 0; + f->carrier = UNSET; f->fname = fname; while (fgets(line, sizeof(line), input)) { @@ -619,8 +629,7 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state) break; } case 't': - arguments->timeout = strtoint(arg, "µs"); - if (arguments->timeout == 0) + if (!strtoint(arg, "µs", &arguments->timeout)) argp_error(state, _("cannot parse timeout `%s'"), arg); break; @@ -629,8 +638,7 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state) arguments->device = arg; break; case 'c': - arguments->carrier = strtoint(arg, "Hz"); - if (arguments->carrier == 0) + if (!strtoint(arg, "Hz", &arguments->carrier)) argp_error(state, _("cannot parse carrier `%s'"), arg); break; case 'e': @@ -639,13 +647,12 @@ static error_t parse_opt(int k, char *arg, struct argp_state *state) argp_error(state, _("cannot parse emitters `%s'"), arg); break; case 'g': - arguments->gap = strtoint(arg, ""); - if (arguments->gap == 0) + if (!strtoint(arg, "", &arguments->gap)) argp_error(state, _("cannot parse gap `%s'"), arg); break; case 'D': - arguments->duty = strtoint(arg, "%"); - if (arguments->duty == 0 || arguments->duty >= 100) + if (!strtoint(arg, "%", &arguments->duty) || + arguments->duty == 0 || arguments->duty >= 100) argp_error(state, _("invalid duty cycle `%s'"), arg); break; case 's': @@ -862,7 +869,7 @@ static int lirc_options(struct arguments *args, int fd, unsigned features) const char *dev = args->device; int rc; - if (args->timeout) { + if (args->timeout != UNSET) { if (features & LIRC_CAN_SET_REC_TIMEOUT) { rc = ioctl(fd, LIRC_SET_REC_TIMEOUT, &args->timeout); if (rc) @@ -910,7 +917,7 @@ static int lirc_options(struct arguments *args, int fd, unsigned features) fprintf(stderr, _("%s: device does not support setting receiver carrier range\n"), dev); } - if (args->carrier) + if (args->carrier != UNSET) lirc_set_send_carrier(fd, dev, features, args->carrier); if (args->duty) { @@ -970,8 +977,12 @@ static void lirc_features(struct arguments *args, int fd, unsigned features) // This ioctl is only supported from kernel 4.18 onwards unsigned timeout; int rc = ioctl(fd, LIRC_GET_REC_TIMEOUT, &timeout); - if (rc == 0) - printf(_(" - Receiving timeout %u microseconds\n"), timeout); + if (rc == 0) { + if (timeout == 0) + printf(_(" - Receiving timeout not set\n")); + else + printf(_(" - Receiving timeout %u microseconds\n"), timeout); + } if (features & LIRC_CAN_SET_REC_TIMEOUT) { unsigned min_timeout, max_timeout; @@ -1074,9 +1085,11 @@ static int lirc_send(struct arguments *args, int fd, unsigned features, struct s f->carrier = protocol_carrier(proto); } - if (args->carrier && f->carrier) - fprintf(stderr, _("warning: %s: carrier specified but overwritten on command line\n"), f->fname); - else if (f->carrier && args->carrier == 0) + if (args->carrier != UNSET) { + if (f->carrier != UNSET) + fprintf(stderr, _("warning: carrier specified but overwritten on command line\n")); + lirc_set_send_carrier(fd, dev, features, args->carrier); + } else if (f->carrier != UNSET) lirc_set_send_carrier(fd, dev, features, f->carrier); size_t size = f->len * sizeof(unsigned); @@ -1220,7 +1233,11 @@ err: int main(int argc, char *argv[]) { - struct arguments args = { .gap = IR_DEFAULT_TIMEOUT }; + struct arguments args = { + .gap = IR_DEFAULT_TIMEOUT, + .carrier = UNSET, + .timeout = UNSET, + }; #ifdef ENABLE_NLS setlocale (LC_ALL, ""); -- 2.26.2