root/drivers/media/rc/ir-imon-decoder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ir_imon_decode_scancode
  2. ir_imon_decode
  3. ir_imon_encode
  4. ir_imon_register
  5. ir_imon_decode_init
  6. ir_imon_decode_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 // ir-imon-decoder.c - handle iMon protocol
   3 //
   4 // Copyright (C) 2018 by Sean Young <sean@mess.org>
   5 
   6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   7 
   8 #include <linux/module.h>
   9 #include "rc-core-priv.h"
  10 
  11 #define IMON_UNIT               415662 /* ns */
  12 #define IMON_BITS               30
  13 #define IMON_CHKBITS            (BIT(30) | BIT(25) | BIT(24) | BIT(22) | \
  14                                  BIT(21) | BIT(20) | BIT(19) | BIT(18) | \
  15                                  BIT(17) | BIT(16) | BIT(14) | BIT(13) | \
  16                                  BIT(12) | BIT(11) | BIT(10) | BIT(9))
  17 
  18 /*
  19  * This protocol has 30 bits. The format is one IMON_UNIT header pulse,
  20  * followed by 30 bits. Each bit is one IMON_UNIT check field, and then
  21  * one IMON_UNIT field with the actual bit (1=space, 0=pulse).
  22  * The check field is always space for some bits, for others it is pulse if
  23  * both the preceding and current bit are zero, else space. IMON_CHKBITS
  24  * defines which bits are of type check.
  25  *
  26  * There is no way to distinguish an incomplete message from one where
  27  * the lower bits are all set, iow. the last pulse is for the lowest
  28  * bit which is 0.
  29  */
  30 enum imon_state {
  31         STATE_INACTIVE,
  32         STATE_BIT_CHK,
  33         STATE_BIT_START,
  34         STATE_FINISHED,
  35         STATE_ERROR,
  36 };
  37 
  38 static void ir_imon_decode_scancode(struct rc_dev *dev)
  39 {
  40         struct imon_dec *imon = &dev->raw->imon;
  41 
  42         /* Keyboard/Mouse toggle */
  43         if (imon->bits == 0x299115b7)
  44                 imon->stick_keyboard = !imon->stick_keyboard;
  45 
  46         if ((imon->bits & 0xfc0000ff) == 0x680000b7) {
  47                 int rel_x, rel_y;
  48                 u8 buf;
  49 
  50                 buf = imon->bits >> 16;
  51                 rel_x = (buf & 0x08) | (buf & 0x10) >> 2 |
  52                         (buf & 0x20) >> 4 | (buf & 0x40) >> 6;
  53                 if (imon->bits & 0x02000000)
  54                         rel_x |= ~0x0f;
  55                 buf = imon->bits >> 8;
  56                 rel_y = (buf & 0x08) | (buf & 0x10) >> 2 |
  57                         (buf & 0x20) >> 4 | (buf & 0x40) >> 6;
  58                 if (imon->bits & 0x01000000)
  59                         rel_y |= ~0x0f;
  60 
  61                 if (rel_x && rel_y && imon->stick_keyboard) {
  62                         if (abs(rel_y) > abs(rel_x))
  63                                 imon->bits = rel_y > 0 ?
  64                                         0x289515b7 : /* KEY_DOWN */
  65                                         0x2aa515b7;  /* KEY_UP */
  66                         else
  67                                 imon->bits = rel_x > 0 ?
  68                                         0x2ba515b7 : /* KEY_RIGHT */
  69                                         0x29a515b7;  /* KEY_LEFT */
  70                 }
  71 
  72                 if (!imon->stick_keyboard) {
  73                         input_report_rel(dev->input_dev, REL_X, rel_x);
  74                         input_report_rel(dev->input_dev, REL_Y, rel_y);
  75 
  76                         input_report_key(dev->input_dev, BTN_LEFT,
  77                                          (imon->bits & 0x00010000) != 0);
  78                         input_report_key(dev->input_dev, BTN_RIGHT,
  79                                          (imon->bits & 0x00040000) != 0);
  80                 }
  81         }
  82 
  83         rc_keydown(dev, RC_PROTO_IMON, imon->bits, 0);
  84 }
  85 
  86 /**
  87  * ir_imon_decode() - Decode one iMON pulse or space
  88  * @dev:        the struct rc_dev descriptor of the device
  89  * @ev:         the struct ir_raw_event descriptor of the pulse/space
  90  *
  91  * This function returns -EINVAL if the pulse violates the state machine
  92  */
  93 static int ir_imon_decode(struct rc_dev *dev, struct ir_raw_event ev)
  94 {
  95         struct imon_dec *data = &dev->raw->imon;
  96 
  97         if (!is_timing_event(ev)) {
  98                 if (ev.reset)
  99                         data->state = STATE_INACTIVE;
 100                 return 0;
 101         }
 102 
 103         dev_dbg(&dev->dev,
 104                 "iMON decode started at state %d bitno %d (%uus %s)\n",
 105                 data->state, data->count, TO_US(ev.duration),
 106                 TO_STR(ev.pulse));
 107 
 108         /*
 109          * Since iMON protocol is a series of bits, if at any point
 110          * we encounter an error, make sure that any remaining bits
 111          * aren't parsed as a scancode made up of less bits.
 112          *
 113          * Note that if the stick is held, then the remote repeats
 114          * the scancode with about 12ms between them. So, make sure
 115          * we have at least 10ms of space after an error. That way,
 116          * we're at a new scancode.
 117          */
 118         if (data->state == STATE_ERROR) {
 119                 if (!ev.pulse && ev.duration > MS_TO_NS(10))
 120                         data->state = STATE_INACTIVE;
 121                 return 0;
 122         }
 123 
 124         for (;;) {
 125                 if (!geq_margin(ev.duration, IMON_UNIT, IMON_UNIT / 2))
 126                         return 0;
 127 
 128                 decrease_duration(&ev, IMON_UNIT);
 129 
 130                 switch (data->state) {
 131                 case STATE_INACTIVE:
 132                         if (ev.pulse) {
 133                                 data->state = STATE_BIT_CHK;
 134                                 data->bits = 0;
 135                                 data->count = IMON_BITS;
 136                         }
 137                         break;
 138                 case STATE_BIT_CHK:
 139                         if (IMON_CHKBITS & BIT(data->count))
 140                                 data->last_chk = ev.pulse;
 141                         else if (ev.pulse)
 142                                 goto err_out;
 143                         data->state = STATE_BIT_START;
 144                         break;
 145                 case STATE_BIT_START:
 146                         data->bits <<= 1;
 147                         if (!ev.pulse)
 148                                 data->bits |= 1;
 149 
 150                         if (IMON_CHKBITS & BIT(data->count)) {
 151                                 if (data->last_chk != !(data->bits & 3))
 152                                         goto err_out;
 153                         }
 154 
 155                         if (!data->count--)
 156                                 data->state = STATE_FINISHED;
 157                         else
 158                                 data->state = STATE_BIT_CHK;
 159                         break;
 160                 case STATE_FINISHED:
 161                         if (ev.pulse)
 162                                 goto err_out;
 163                         ir_imon_decode_scancode(dev);
 164                         data->state = STATE_INACTIVE;
 165                         break;
 166                 }
 167         }
 168 
 169 err_out:
 170         dev_dbg(&dev->dev,
 171                 "iMON decode failed at state %d bitno %d (%uus %s)\n",
 172                 data->state, data->count, TO_US(ev.duration),
 173                 TO_STR(ev.pulse));
 174 
 175         data->state = STATE_ERROR;
 176 
 177         return -EINVAL;
 178 }
 179 
 180 /**
 181  * ir_imon_encode() - Encode a scancode as a stream of raw events
 182  *
 183  * @protocol:   protocol to encode
 184  * @scancode:   scancode to encode
 185  * @events:     array of raw ir events to write into
 186  * @max:        maximum size of @events
 187  *
 188  * Returns:     The number of events written.
 189  *              -ENOBUFS if there isn't enough space in the array to fit the
 190  *              encoding. In this case all @max events will have been written.
 191  */
 192 static int ir_imon_encode(enum rc_proto protocol, u32 scancode,
 193                           struct ir_raw_event *events, unsigned int max)
 194 {
 195         struct ir_raw_event *e = events;
 196         int i, pulse;
 197 
 198         if (!max--)
 199                 return -ENOBUFS;
 200         init_ir_raw_event_duration(e, 1, IMON_UNIT);
 201 
 202         for (i = IMON_BITS; i >= 0; i--) {
 203                 if (BIT(i) & IMON_CHKBITS)
 204                         pulse = !(scancode & (BIT(i) | BIT(i + 1)));
 205                 else
 206                         pulse = 0;
 207 
 208                 if (pulse == e->pulse) {
 209                         e->duration += IMON_UNIT;
 210                 } else {
 211                         if (!max--)
 212                                 return -ENOBUFS;
 213                         init_ir_raw_event_duration(++e, pulse, IMON_UNIT);
 214                 }
 215 
 216                 pulse = !(scancode & BIT(i));
 217 
 218                 if (pulse == e->pulse) {
 219                         e->duration += IMON_UNIT;
 220                 } else {
 221                         if (!max--)
 222                                 return -ENOBUFS;
 223                         init_ir_raw_event_duration(++e, pulse, IMON_UNIT);
 224                 }
 225         }
 226 
 227         if (e->pulse)
 228                 e++;
 229 
 230         return e - events;
 231 }
 232 
 233 static int ir_imon_register(struct rc_dev *dev)
 234 {
 235         struct imon_dec *imon = &dev->raw->imon;
 236 
 237         imon->stick_keyboard = false;
 238 
 239         return 0;
 240 }
 241 
 242 static struct ir_raw_handler imon_handler = {
 243         .protocols      = RC_PROTO_BIT_IMON,
 244         .decode         = ir_imon_decode,
 245         .encode         = ir_imon_encode,
 246         .carrier        = 38000,
 247         .raw_register   = ir_imon_register,
 248         .min_timeout    = IMON_UNIT * IMON_BITS * 2,
 249 };
 250 
 251 static int __init ir_imon_decode_init(void)
 252 {
 253         ir_raw_handler_register(&imon_handler);
 254 
 255         pr_info("IR iMON protocol handler initialized\n");
 256         return 0;
 257 }
 258 
 259 static void __exit ir_imon_decode_exit(void)
 260 {
 261         ir_raw_handler_unregister(&imon_handler);
 262 }
 263 
 264 module_init(ir_imon_decode_init);
 265 module_exit(ir_imon_decode_exit);
 266 
 267 MODULE_LICENSE("GPL");
 268 MODULE_AUTHOR("Sean Young <sean@mess.org>");
 269 MODULE_DESCRIPTION("iMON IR protocol decoder");

/* [<][>][^][v][top][bottom][index][help] */