Skip to contentSkip to conversation

keytable: add support for keymap with raw literal strings

PATCH Superseded Sean Young 1 participant 1 message Aug 8, 2019 Media (V4L/DVB)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Sean Young

author
#0 lore raw

PATCH 1/1 keytable: add support for keymap with raw literal strings

This adds support for converting lircd raw_codes remote definitions. This means that the vast majority of lircd files can be converted.

This feature requires loops in BPF programs so this is only supported in kernel 5.3 onwards.

---
 contrib/lircd2toml.py                    |  52 ++++++---
 utils/keytable/bpf_load.c                |  84 ++++++++++++++-
 utils/keytable/bpf_load.h                |   9 +-
 utils/keytable/bpf_protocols/Makefile.am |   2 +-
 utils/keytable/bpf_protocols/bitmap.h    |  36 +++++++
 utils/keytable/bpf_protocols/raw.c       | 131 +++++++++++++++++++++++
 utils/keytable/keytable.c                | 127 +++++++++++++++++++++-
 utils/keytable/rc_keymap.5.in            |  15 ++-
 8 files changed, 435 insertions(+), 21 deletions(-)
 create mode 100644 utils/keytable/bpf_protocols/bitmap.h
 create mode 100644 utils/keytable/bpf_protocols/raw.c
contrib/lircd2toml.py +40 -12
index 9b93f198..2aebfb0b 100755
@@ -146,14 +146,14 @@ class LircdParser:
             a = line.split()
             if a[0] == 'name':
                 if len(codes) > 0:
-                    raw_codes.append({ 'name': name, 'codes': codes })
+                    raw_codes.append({ 'keycode': name, 'raw': codes })
                 name = line.split(maxsplit=2)[1]
                 if not name.startswith('KEY_'):
                     name = 'KEY_' + name.upper()
                 codes = []
             elif a[0] == 'end':
                 if len(codes) > 0:
-                    raw_codes.append({ 'name': name, 'codes': codes })
+                    raw_codes.append({ 'keycode': name, 'raw': codes })
                 return raw_codes
             else:
                 for v in a:
@@ -224,6 +224,8 @@ class Converter:
             return self.convert_rcmm()
         elif 'space_enc' in flags:
             return self.convert_space_enc()
+        elif 'raw_codes' in flags:
+            return self.convert_raw_codes()
         else:
             self.error('Cannot convert remote with flags: {}'.format('|'.join(flags)))
 
@@ -567,6 +569,16 @@ class Converter:
 
         return res
 
+    def convert_raw_codes(self):
+        res  = {
+            'protocol': 'raw',
+            'params': {},
+            'raw': self.remote['raw_codes'],
+            'name': self.remote['name']
+        }
+
+        return res
+
 def escapeString(s):
     return "'" + s.encode('unicode_escape').decode('utf-8') + "'"
 
@@ -576,16 +588,32 @@ def writeTOMLFile(fh, remote):
     print('protocol = {}'.format(escapeString(remote['protocol'])), file=fh)
     for p in remote['params']:
         print('{} = {}'.format(p, remote['params'][p]), file=fh)
-    print('[protocols.scancodes]', file=fh)
-    # find the largest scancode
-    length=1
-    for c in remote['map']:
-        length=max(length, c.bit_length())
-
-    # width seems to include '0x', hence the + 2
-    width = math.ceil(length/4) + 2
-    for c in remote['map']:
-        print('{:#0{width}x} = {}'.format(c, escapeString(remote['map'][c]), width=width), file=fh)
+
+    if 'map' in remote:
+        print('[protocols.scancodes]', file=fh)
+        # find the largest scancode
+        length=1
+        for c in remote['map']:
+            length=max(length, c.bit_length())
+
+        # width seems to include '0x', hence the + 2
+        width = math.ceil(length/4) + 2
+        for c in remote['map']:
+            print('{:#0{width}x} = {}'.format(c, escapeString(remote['map'][c]), width=width), file=fh)
+
+    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='')
+                else:
+                    print(', {}'.format(v), file=fh, end='')
+                first = False
+
+            print(' ]', file=fh)
 
     return True
 
utils/keytable/bpf_load.c +80 -4

132 lines not on this page · raw message

utils/keytable/bpf_load.h +8 -1
index 2775607f..471600bb 100644
@@ -24,6 +24,13 @@ struct bpf_map_data {
 	struct bpf_load_map_def def;
 };
 
+struct raw_entry {
+	struct raw_entry *next;
+	u_int32_t scancode;
+	u_int32_t raw_length;
+	u_int32_t raw[1];
+};
+
 /* parses elf file compiled by llvm .c->.o
  * . parses 'maps' section and creates maps via BPF syscall
  * . parses 'license' section and passes it to syscall
@@ -36,7 +43,7 @@ struct bpf_map_data {
  *
  * returns zero on success
  */
-int load_bpf_file(const char *path, int lirc_fd, struct toml_table_t *toml);
+int load_bpf_file(const char *path, int lirc_fd, struct toml_table_t *toml, struct raw_entry *raw);
 
 int bpf_param(const char *name, int *val);
 
utils/keytable/bpf_protocols/Makefile.am +1 -1
index bca3bdec..d9facbc9 100644
@@ -10,7 +10,7 @@ CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - </dev/null 2>&1 \
 %.o: %.c bpf_helpers.h
 	$(CLANG) $(CLANG_SYS_INCLUDES) -D__linux__ -I$(top_srcdir)/include -target bpf -O2 -c $<
 
-PROTOCOLS = grundig.o pulse_distance.o pulse_length.o rc_mm.o manchester.o xbox-dvd.o imon_rsc.o
+PROTOCOLS = grundig.o pulse_distance.o pulse_length.o rc_mm.o manchester.o xbox-dvd.o imon_rsc.o raw.o
 
 all: $(PROTOCOLS)
 
utils/keytable/bpf_protocols/bitmap.h new file +36 -0
new file mode 100644
index 00000000..e3d731ad
@@ -0,0 +1,36 @@
+
+#ifndef __BITMAP_H__
+#define __BITMAP_H__
+
+#include "string.h"
+
+#define BITS_PER_LONG 64
+#define BITS_TO_LONG(n) \
+	(((n) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
+
+#define DECLARE_BITMAP(name, bits) \
+	unsigned long name[BITS_TO_LONG(bits)]
+
+static void inline bitmap_zero(unsigned long *bitmap, int bits)
+{
+	for (int i = 0; i < BITS_TO_LONG(bits); i++)
+		bitmap[i] = 0;
+}
+
+static void inline bitmap_fill(unsigned long *bitmap, int bits)
+{
+	for (int i = 0; i < BITS_TO_LONG(bits); i++)
+		bitmap[i] = ~0;
+}
+
+#define bitmap_set(b, n) \
+	b[n / BITS_PER_LONG] |= 1 << (n % BITS_PER_LONG)
+
+#define bitmap_clear(b, n) \
+	b[n / BITS_PER_LONG] &= ~(1 << (n % BITS_PER_LONG))
+
+#define bitmap_test(b, n) \
+	(b[n / BITS_PER_LONG] & (1 << (n % BITS_PER_LONG))) != 0
+
+#endif
utils/keytable/bpf_protocols/raw.c new file +131 -0

131 lines not on this page · raw message

utils/keytable/keytable.c +126 -1

163 lines not on this page · raw message

utils/keytable/rc_keymap.5.in +13 -2
index c9e672d7..f2897631 100644
@@ -21,7 +21,7 @@ name than the file name, e.g. the model number.
 The \fBprotocol\fR field specifies the protocol. This can either be one of the
 linux kernel decoders, in which case it is \fBnec\fR, \fBrc\-5\fR, \fBrc\-6\fR,
 \fBjvc\fR, \fBsony\fR, \fBsanyo\fR, \fBrc\-5\-sz\fR, \fBsharp\fR,
-\fBmce\-kbd\fR, \fBxmp\fR, \fBimon\fR, \fBrc\-mm\fR, \fBother\fR or
+\fBmce\-kbd\fR, \fBxmp\fR, \fBimon\fR, \fBrc\-mm\fR, \fBraw\fR, \fBother\fR or
 \fBunknown\fR. If it does not match any of these entries, then it is assumed
 to be a BPF based decoder. The \fBunknown\fR and \fBother\fR are protocols
 decoded by specific RC devices where the protocol is either unknown or
@@ -52,7 +52,8 @@ Protocol \fBrc\-mm\fR has variants \fBrc-mm-12\fR, \fBrc-mm-24\fR, and
 \fBrc-mm-32\fR.
 .SS Scancodes field
 The \fBscancodes\fR table list the scancodes and the mapping to linux input
-key events. Multiple scancodes can map to the same key event.
+key events. Multiple scancodes can map to the same key event. This field
+is not present for \fBraw\fR protocols.
 .PP
 If the scancode start with 0x, it is interpreted as a hexadecimal number. If
 it starts with a 0, it is interpreted as an octal number.
@@ -60,6 +61,16 @@ it starts with a 0, it is interpreted as an octal number.
 The key events are listed in the \fBinput-event-codes.h\fR header file.
 Examples are \fBKEY_ENTER\fR, \fBKEY_ESC\fR or \fBBTN_LEFT\fR for the left
 mouse button.
+.SS Raw field
+If the protocol is \fBraw\fR, the \fBraw\fR field is an array of keycode
+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.
 .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
Signature · 1 line
2.21.0