Many programs and documentation lists raw IR a list of ints:

        +8800 –4400 +550 –1650 +550 –1650 +550 –1650 +550 –550 +550

The + and - are optional and are there for readability.

I think this is much nicer format that 1) toml arrays and 2) lirc
pulse space format. In fact, I think "ir-ctl -r" should output this
format too, and support it for sending.

As a first start, let's update the toml rc keymap format; the existing
toml raw array has not been in a release.

Signed-off-by: Sean Young <s...@mess.org>
---
 contrib/lircd2toml.py         |  16 ++---
 utils/common/keymap.c         | 126 ++++++++++++++++++++++------------
 utils/keytable/rc_keymap.5.in |   9 +--
 3 files changed, 96 insertions(+), 55 deletions(-)

diff --git a/contrib/lircd2toml.py b/contrib/lircd2toml.py
index 05729239..cfa648ed 100755
--- a/contrib/lircd2toml.py
+++ b/contrib/lircd2toml.py
@@ -604,16 +604,16 @@ def writeTOMLFile(fh, remote):
     elif 'raw' in remote:
         for raw in remote['raw']:
             print('[[protocols.raw]]', file=fh)
-            print('keycode = {}\nraw = 
['.format(escapeString(raw['keycode'])), file=fh, end='')
-            first = True
-            for v in raw['raw']:
-                if first:
-                    print(' {}'.format(v), file=fh, end='')
+            print('keycode = {}\nraw = 
\''.format(escapeString(raw['keycode'])), file=fh, end='')
+            for i, v in enumerate(raw['raw']):
+                if i == 0:
+                    print('+{}'.format(v), file=fh, end='')
+                elif i % 2 == 1:
+                    print(' -{}'.format(v), file=fh, end='')
                 else:
-                    print(', {}'.format(v), file=fh, end='')
-                first = False
+                    print(' +{}'.format(v), file=fh, end='')
 
-            print(' ]', file=fh)
+            print('\'', file=fh)
 
     return True
 
diff --git a/utils/common/keymap.c b/utils/common/keymap.c
index 9c49b442..9ca599a0 100644
--- a/utils/common/keymap.c
+++ b/utils/common/keymap.c
@@ -177,73 +177,113 @@ err_einval:
        return EINVAL;
 }
 
+static error_t parse_rawir_string(const char *fname, char *str, struct 
raw_entry **entry)
+{
+       struct raw_entry *re;
+       const char *p;
+       char *copy;
+       int i, size = 0;
+
+       // First do one scan so that we know the length
+       copy = strdup(str);
+       p = strtok(copy, "\n\t\v ,");
+       while (p) {
+               size++;
+               p = strtok(NULL, "\n\t\v ,");
+       }
+
+       re = calloc(1, sizeof(*re) + sizeof(re->raw[0]) * size);
+       if (!re) {
+               fprintf(stderr, _("Failed to allocate memory"));
+               free(copy);
+               return EINVAL;
+       }
+
+       // Second scan to extract values and validate
+       strcpy(copy, str);
+       p = strtok(copy, "\n\t\v ,");
+       i = 0;
+       while (p) {
+               long int value;
+               char *q;
+
+               value = strtoll(p, &q, 10);
+               if (*q || value == 0 || errno) {
+                       fprintf(stderr, _("%s: incorrect raw value `%s'"),
+                               fname, p);
+                       free(copy);
+                       return EINVAL;
+               }
+
+               if (value < 0) {
+                       if (i % 2)
+                               value = -value;
+                       else {
+                               fprintf(stderr, _("%s: negative raw value `%ld` 
at position %d only allowed for gaps/spaces"),
+                                       fname, value, i);
+                               free(copy);
+                               return EINVAL;
+                       }
+               }
+
+               if (value <= 0 || value > USHRT_MAX) {
+                       fprintf(stderr, _("%s: raw value %ld out of range"),
+                               fname, value);
+                       free(copy);
+                       return EINVAL;
+               }
+
+               re->raw[i++] = value;
+
+               p = strtok(NULL, "\n\t\v ,");
+       }
+
+       free(copy);
+       re->raw_length = size;
+
+       *entry = re;
+
+       return 0;
+}
+
 static error_t parse_toml_raw_part(const char *fname, struct toml_array_t 
*raw, struct keymap *map, bool verbose)
 {
+       char *keycode, *raw_str;
        struct toml_table_t *t;
-       struct toml_array_t *rawarray;
        struct raw_entry *re;
-       const char *rkeycode;
-       int ind = 0, length;
-       char *keycode;
+       const char *traw;
+       int ind = 0;
 
        while ((t = toml_table_at(raw, ind++)) != NULL) {
-               rkeycode = toml_raw_in(t, "keycode");
-               if (!rkeycode) {
+               traw = toml_raw_in(t, "keycode");
+               if (!traw) {
                        fprintf(stderr, _("%s: invalid keycode for raw entry 
%d\n"),
                                fname, ind);
                        return EINVAL;
                }
 
-               if (toml_rtos(rkeycode, &keycode)) {
+               if (toml_rtos(traw, &keycode)) {
                        fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
-                               fname, rkeycode);
+                               fname, traw);
                        return EINVAL;
                }
 
-               rawarray = toml_array_in(t, "raw");
-               if (!rawarray) {
-                       fprintf(stderr, _("%s: missing raw array for entry 
%d\n"),
+               traw = toml_raw_in(t, "raw");
+               if (!traw) {
+                       fprintf(stderr, _("%s: missing raw value for entry 
%d\n"),
                                fname, ind);
                        return EINVAL;
                }
 
-               // determine length of array
-               length = 0;
-               while (toml_raw_at(rawarray, length) != NULL)
-                       length++;
-
-               if (!(length % 2)) {
-                       fprintf(stderr, _("%s: raw array must have odd length 
rather than %d\n"),
-                               fname, length);
+               if (toml_rtos(traw, &raw_str)) {
+                       fprintf(stderr, _("%s: bad value `%s' for keycode\n"),
+                               fname, traw);
                        return EINVAL;
                }
 
-               re = calloc(1, sizeof(*re) + sizeof(re->raw[0]) * length);
-               if (!re) {
-                       fprintf(stderr, _("Failed to allocate memory"));
+               if (parse_rawir_string(fname, raw_str, &re))
                        return EINVAL;
-               }
-
-               for (int i=0; i<length; i++) {
-                       const char *s = toml_raw_at(rawarray, i);
-                       int64_t v;
-
-                       if (toml_rtoi(s, &v) || v == 0) {
-                               fprintf(stderr, _("%s: incorrect raw value 
`%s'"),
-                                       fname, s);
-                               return EINVAL;
-                       }
-
-                       if (v <= 0 || v > USHRT_MAX) {
-                               fprintf(stderr, _("%s: raw value %ld out of 
range"),
-                                       fname, v);
-                               return EINVAL;
-                       }
-
-                       re->raw[i] = v;
-               }
 
-               re->raw_length = length;
                re->keycode = strdup(keycode);
                re->next = map->raw;
                map->raw = re;
diff --git a/utils/keytable/rc_keymap.5.in b/utils/keytable/rc_keymap.5.in
index 00599755..12f05a1d 100644
--- a/utils/keytable/rc_keymap.5.in
+++ b/utils/keytable/rc_keymap.5.in
@@ -67,10 +67,11 @@ to raw mapping. For each entry, there is a \fBkeycode\fR 
field and \fBraw\fR
 field. The \fBkeycode\fR is a linux input event, as explained the scancodes
 section.
 .PP
-The \fBraw\fR field is an array of integers. These are the pulse and space
-values of the IR message. The first is a pulse value in microseconds, and
-the second a space, third pulse, etc. There should be an odd number of fields
-so that the last entry is a pulse.
+The \fBraw\fR field is an string, which lists pulse and space values,
+separated by whitespace.  The first is a pulse value in microseconds, and
+the second a space, third pulse, etc. The space values can be preceded by
+a - sign and the pulse value can be preceded by a +sign.
+There should be an odd number of fields so that the last entry is a pulse.
 .SS Remaining fields (BPF parameters)
 If the protocol is a BPF based decoder, it may have any number of numeric
 parameters. These parameters are used to support protocols with non-standard
-- 
2.21.0

Reply via email to