Source
x
// SPDX-License-Identifier: GPL-2.0+
// ir-imon-decoder.c - handle iMon protocol
//
// Copyright (C) 2018 by Sean Young <sean@mess.org>
/* ns */
/*
* This protocol has 30 bits. The format is one IMON_UNIT header pulse,
* followed by 30 bits. Each bit is one IMON_UNIT check field, and then
* one IMON_UNIT field with the actual bit (1=space, 0=pulse).
* The check field is always space for some bits, for others it is pulse if
* both the preceding and current bit are zero, else space. IMON_CHKBITS
* defines which bits are of type check.
*
* There is no way to distinguish an incomplete message from one where
* the lower bits are all set, iow. the last pulse is for the lowest
* bit which is 0.
*/
enum imon_state {
STATE_INACTIVE,
STATE_BIT_CHK,
STATE_BIT_START,
STATE_FINISHED,
STATE_ERROR,
};
static void ir_imon_decode_scancode(struct rc_dev *dev)
{
struct imon_dec *imon = &dev->raw->imon;
/* Keyboard/Mouse toggle */
if (imon->bits == 0x299115b7)
imon->stick_keyboard = !imon->stick_keyboard;
if ((imon->bits & 0xfc0000ff) == 0x680000b7) {
int rel_x, rel_y;
u8 buf;
buf = imon->bits >> 16;
rel_x = (buf & 0x08) | (buf & 0x10) >> 2 |
(buf & 0x20) >> 4 | (buf & 0x40) >> 6;
if (imon->bits & 0x02000000)
rel_x |= ~0x0f;
buf = imon->bits >> 8;
rel_y = (buf & 0x08) | (buf & 0x10) >> 2 |
(buf & 0x20) >> 4 | (buf & 0x40) >> 6;
if (imon->bits & 0x01000000)
rel_y |= ~0x0f;
if (rel_x && rel_y && imon->stick_keyboard) {
if (abs(rel_y) > abs(rel_x))
imon->bits = rel_y > 0 ?
0x289515b7 : /* KEY_DOWN */
0x2aa515b7; /* KEY_UP */
else
imon->bits = rel_x > 0 ?
0x2ba515b7 : /* KEY_RIGHT */
0x29a515b7; /* KEY_LEFT */
}
if (!imon->stick_keyboard) {
input_report_rel(dev->input_dev, REL_X, rel_x);
input_report_rel(dev->input_dev, REL_Y, rel_y);
input_report_key(dev->input_dev, BTN_LEFT,
(imon->bits & 0x00010000) != 0);
input_report_key(dev->input_dev, BTN_RIGHT,
(imon->bits & 0x00040000) != 0);
}
}
rc_keydown(dev, RC_PROTO_IMON, imon->bits, 0);
}
/**
* ir_imon_decode() - Decode one iMON 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
*/