Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
// SPDX-License-Identifier: GPL-2.0+
// ir-rcmm-decoder.c - A decoder for the RCMM IR protocol
//
// Copyright (C) 2018 by Patrick Lerda <patrick9876@free.fr>
#include "rc-core-priv.h"
#include <linux/module.h>
#define RCMM_UNIT 166 /* microseconds */
#define RCMM_PREFIX_PULSE 417 /* 166.666666666666*2.5 */
#define RCMM_PULSE_0 278 /* 166.666666666666*(1+2/3) */
#define RCMM_PULSE_1 444 /* 166.666666666666*(2+2/3) */
#define RCMM_PULSE_2 611 /* 166.666666666666*(3+2/3) */
#define RCMM_PULSE_3 778 /* 166.666666666666*(4+2/3) */
enum rcmm_state {
<------>STATE_INACTIVE,
<------>STATE_LOW,
<------>STATE_BUMP,
<------>STATE_VALUE,
<------>STATE_FINISHED,
};
static bool rcmm_mode(const struct rcmm_dec *data)
{
<------>return !((0x000c0000 & data->bits) == 0x000c0000);
}
static int rcmm_miscmode(struct rc_dev *dev, struct rcmm_dec *data)
{
<------>switch (data->count) {
<------>case 24:
<------><------>if (dev->enabled_protocols & RC_PROTO_BIT_RCMM24) {
<------><------><------>rc_keydown(dev, RC_PROTO_RCMM24, data->bits, 0);
<------><------><------>data->state = STATE_INACTIVE;
<------><------><------>return 0;
<------><------>}
<------><------>return -1;
<------>case 12:
<------><------>if (dev->enabled_protocols & RC_PROTO_BIT_RCMM12) {
<------><------><------>rc_keydown(dev, RC_PROTO_RCMM12, data->bits, 0);
<------><------><------>data->state = STATE_INACTIVE;
<------><------><------>return 0;
<------><------>}
<------><------>return -1;
<------>}
<------>return -1;
}
/**
* ir_rcmm_decode() - Decode one RCMM pulse or space
* @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
<------>struct rcmm_dec *data = &dev->raw->rcmm;
<------>u32 scancode;
<------>u8 toggle;
<------>int value;
<------>if (!(dev->enabled_protocols & (RC_PROTO_BIT_RCMM32 |
<------><------><------><------><------>RC_PROTO_BIT_RCMM24 |
<------><------><------><------><------>RC_PROTO_BIT_RCMM12)))
<------><------>return 0;
<------>if (!is_timing_event(ev)) {
<------><------>if (ev.reset)
<------><------><------>data->state = STATE_INACTIVE;
<------><------>return 0;
<------>}
<------>switch (data->state) {
<------>case STATE_INACTIVE:
<------><------>if (!ev.pulse)
<------><------><------>break;
<------><------>if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT))
<------><------><------>break;
<------><------>data->state = STATE_LOW;
<------><------>data->count = 0;
<------><------>data->bits = 0;
<------><------>return 0;
<------>case STATE_LOW:
<------><------>if (ev.pulse)
<------><------><------>break;
<------><------>if (!eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT))
<------><------><------>break;
<------><------>data->state = STATE_BUMP;
<------><------>return 0;
<------>case STATE_BUMP:
<------><------>if (!ev.pulse)
<------><------><------>break;
<------><------>if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
<------><------><------>break;
<------><------>data->state = STATE_VALUE;
<------><------>return 0;
<------>case STATE_VALUE:
<------><------>if (ev.pulse)
<------><------><------>break;
<------><------>if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
<------><------><------>value = 0;
<------><------>else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
<------><------><------>value = 1;
<------><------>else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
<------><------><------>value = 2;
<------><------>else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
<------><------><------>value = 3;
<------><------>else
<------><------><------>value = -1;
<------><------>if (value == -1) {
<------><------><------>if (!rcmm_miscmode(dev, data))
<------><------><------><------>return 0;
<------><------><------>break;
<------><------>}
<------><------>data->bits <<= 2;
<------><------>data->bits |= value;
<------><------>data->count += 2;
<------><------>if (data->count < 32)
<------><------><------>data->state = STATE_BUMP;
<------><------>else
<------><------><------>data->state = STATE_FINISHED;
<------><------>return 0;
<------>case STATE_FINISHED:
<------><------>if (!ev.pulse)
<------><------><------>break;
<------><------>if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
<------><------><------>break;
<------><------>if (rcmm_mode(data)) {
<------><------><------>toggle = !!(0x8000 & data->bits);
<------><------><------>scancode = data->bits & ~0x8000;
<------><------>} else {
<------><------><------>toggle = 0;
<------><------><------>scancode = data->bits;
<------><------>}
<------><------>if (dev->enabled_protocols & RC_PROTO_BIT_RCMM32) {
<------><------><------>rc_keydown(dev, RC_PROTO_RCMM32, scancode, toggle);
<------><------><------>data->state = STATE_INACTIVE;
<------><------><------>return 0;
<------><------>}
<------><------>break;
<------>}
<------>dev_dbg(&dev->dev, "RC-MM decode failed at count %d state %d (%uus %s)\n",
<------><------>data->count, data->state, ev.duration, TO_STR(ev.pulse));
<------>data->state = STATE_INACTIVE;
<------>return -EINVAL;
}
static const int rcmmspace[] = {
<------>RCMM_PULSE_0,
<------>RCMM_PULSE_1,
<------>RCMM_PULSE_2,
<------>RCMM_PULSE_3,
};
static int ir_rcmm_rawencoder(struct ir_raw_event **ev, unsigned int max,
<------><------><------> unsigned int n, u32 data)
{
<------>int i;
<------>int ret;
<------>ret = ir_raw_gen_pulse_space(ev, &max, RCMM_PREFIX_PULSE, RCMM_PULSE_0);
<------>if (ret)
<------><------>return ret;
<------>for (i = n - 2; i >= 0; i -= 2) {
<------><------>const unsigned int space = rcmmspace[(data >> i) & 3];
<------><------>ret = ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, space);
<------><------>if (ret)
<------><------><------>return ret;
<------>}
<------>return ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, RCMM_PULSE_3 * 2);
}
static int ir_rcmm_encode(enum rc_proto protocol, u32 scancode,
<------><------><------> struct ir_raw_event *events, unsigned int max)
{
<------>struct ir_raw_event *e = events;
<------>int ret;
<------>switch (protocol) {
<------>case RC_PROTO_RCMM32:
<------><------>ret = ir_rcmm_rawencoder(&e, max, 32, scancode);
<------><------>break;
<------>case RC_PROTO_RCMM24:
<------><------>ret = ir_rcmm_rawencoder(&e, max, 24, scancode);
<------><------>break;
<------>case RC_PROTO_RCMM12:
<------><------>ret = ir_rcmm_rawencoder(&e, max, 12, scancode);
<------><------>break;
<------>default:
<------><------>ret = -EINVAL;
<------>}
<------>if (ret < 0)
<------><------>return ret;
<------>return e - events;
}
static struct ir_raw_handler rcmm_handler = {
<------>.protocols = RC_PROTO_BIT_RCMM32 |
<------><------><------> RC_PROTO_BIT_RCMM24 |
<------><------><------> RC_PROTO_BIT_RCMM12,
<------>.decode = ir_rcmm_decode,
<------>.encode = ir_rcmm_encode,
<------>.carrier = 36000,
<------>.min_timeout = RCMM_PULSE_3 + RCMM_UNIT,
};
static int __init ir_rcmm_decode_init(void)
{
<------>ir_raw_handler_register(&rcmm_handler);
<------>pr_info("IR RCMM protocol handler initialized\n");
<------>return 0;
}
static void __exit ir_rcmm_decode_exit(void)
{
<------>ir_raw_handler_unregister(&rcmm_handler);
}
module_init(ir_rcmm_decode_init);
module_exit(ir_rcmm_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick Lerda");
MODULE_DESCRIPTION("RCMM IR protocol decoder");