aboutsummaryrefslogtreecommitdiffstats
path: root/utils/ir-ctl/bpf_encoder.c
blob: 1d075d94e4f35780de9b3c2f93e6716fc502624a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* SPDX-License-Identifier: GPL-2.0 */

#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <argp.h>

#include "keymap.h"

// Some keymaps use BPF decoders, so the kernel has no idea how to encode
// them. We need user-space encoders for these.
//
// This encoders should match what the BPF decoders in
// utils/keytable/bpf_protocols/*.c decode.

static void encode_pulse_distance(struct keymap *map, uint32_t scancode, int *buf, int *length)
{
	int len = 0, bits, i;

	buf[len++] = keymap_param(map, "header_pulse", 2125);
	buf[len++] = keymap_param(map, "header_space", 1875);

	bits = keymap_param(map, "bits", 4);

	if (keymap_param(map, "reverse", 0)) {
		for (i = 0; i < bits; i++) {
			buf[len++] = keymap_param(map, "bit_pulse", 625);

			if (scancode & (1 << i))
				buf[len++] = keymap_param(map, "bit_1_space", 1625);
			else
				buf[len++] = keymap_param(map, "bit_0_space", 375);
		}
	} else {
		for (i = bits - 1; i >= 0; i--) {
			buf[len++] = keymap_param(map, "bit_pulse", 625);

			if (scancode & (1 << i))
				buf[len++] = keymap_param(map, "bit_1_space", 1625);
			else
				buf[len++] = keymap_param(map, "bit_0_space", 375);
		}
	}

	buf[len++] = keymap_param(map, "trailer_pulse", 625);

	*length = len;
}

static void encode_pulse_length(struct keymap *map, uint32_t scancode, int *buf, int *length)
{
	int len = 0, bits, i;

	buf[len++] = keymap_param(map, "header_pulse", 2125);
	buf[len++] = keymap_param(map, "header_space", 1875);

	bits = keymap_param(map, "bits", 4);

	if (keymap_param(map, "reverse", 0)) {
		for (i = 0; i < bits; i++) {
			if (scancode & (1 << i))
				buf[len++] = keymap_param(map, "bit_1_space", 1625);
			else
				buf[len++] = keymap_param(map, "bit_0_space", 375);

			buf[len++] = keymap_param(map, "bit_pulse", 625);
		}
	} else {
		for (i = bits - 1; i >= 0; i--) {
			if (scancode & (1 << i))
				buf[len++] = keymap_param(map, "bit_1_space", 1625);
			else
				buf[len++] = keymap_param(map, "bit_0_space", 375);

			buf[len++] = keymap_param(map, "bit_pulse", 625);
		}
	}

	*length = len;
}

static void manchester_advance_space(int *buf, int *len, unsigned length)
{
	if (*len % 2)
		buf[*len] += length;
	else
		buf[++(*len)] = length;
}

static void manchester_advance_pulse(int *buf, int *len, unsigned length)
{
	if (*len % 2)
		buf[++(*len)] = length;
	else
		buf[*len] += length;
}

static void encode_manchester(struct keymap *map, uint32_t scancode, int *buf, int *length)
{
	int len = 0, bits, i;

	bits = keymap_param(map, "bits", 14);

	for (i = bits - 1; i >= 0; i--) {
		if (scancode & (1 << i)) {
			manchester_advance_pulse(buf, &len, keymap_param(map, "one_pulse", 888));
			manchester_advance_space(buf, &len, keymap_param(map, "one_space", 888));
		} else {
			manchester_advance_space(buf, &len, keymap_param(map, "zero_space", 888));
			manchester_advance_pulse(buf, &len, keymap_param(map, "zero_pulse", 888));
		}
	}

	/* drop any trailing pulse */
        *length = (len % 2) ? len : len + 1;
}

bool encode_bpf_protocol(struct keymap *map, uint32_t scancode, int *buf, int *length)
{
	if (!strcmp(map->protocol, "pulse_distance")) {
		encode_pulse_distance(map, scancode, buf, length);
		return true;
	}

	if (!strcmp(map->protocol, "pulse_length")) {
		encode_pulse_length(map, scancode, buf, length);
		return true;
	}

	if (!strcmp(map->protocol, "manchester")) {
		encode_manchester(map, scancode, buf, length);
		return true;
	}

	return false;
}

Privacy Policy