blob: 1d075d94e4f35780de9b3c2f93e6716fc502624a [file] [log] [blame]
/* 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;
}