linux/drivers/media/rc/ir-rc6-decoder.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
   3 *
   4 * Copyright (C) 2010 by David H\xC3\xA4rdeman <david@hardeman.nu>
   5 */
   6
   7#include "rc-core-priv.h"
   8#include <linux/module.h>
   9
  10/*
  11 * This decoder currently supports:
  12 * RC6-0-16     (standard toggle bit in header)
  13 * RC6-6A-20    (no toggle bit)
  14 * RC6-6A-24    (no toggle bit)
  15 * RC6-6A-32    (MCE version with toggle bit in body)
  16 */
  17
  18#define RC6_UNIT                444     /* microseconds */
  19#define RC6_HEADER_NBITS        4       /* not including toggle bit */
  20#define RC6_0_NBITS             16
  21#define RC6_6A_32_NBITS         32
  22#define RC6_6A_NBITS            128     /* Variable 8..128 */
  23#define RC6_PREFIX_PULSE        (6 * RC6_UNIT)
  24#define RC6_PREFIX_SPACE        (2 * RC6_UNIT)
  25#define RC6_BIT_START           (1 * RC6_UNIT)
  26#define RC6_BIT_END             (1 * RC6_UNIT)
  27#define RC6_TOGGLE_START        (2 * RC6_UNIT)
  28#define RC6_TOGGLE_END          (2 * RC6_UNIT)
  29#define RC6_SUFFIX_SPACE        (6 * RC6_UNIT)
  30#define RC6_MODE_MASK           0x07    /* for the header bits */
  31#define RC6_STARTBIT_MASK       0x08    /* for the header bits */
  32#define RC6_6A_MCE_TOGGLE_MASK  0x8000  /* for the body bits */
  33#define RC6_6A_LCC_MASK         0xffff0000 /* RC6-6A-32 long customer code mask */
  34#define RC6_6A_MCE_CC           0x800f0000 /* MCE customer code */
  35#define RC6_6A_ZOTAC_CC         0x80340000 /* Zotac customer code */
  36#define RC6_6A_KATHREIN_CC      0x80460000 /* Kathrein RCU-676 customer code */
  37#ifndef CHAR_BIT
  38#define CHAR_BIT 8      /* Normally in <limits.h> */
  39#endif
  40
  41enum rc6_mode {
  42        RC6_MODE_0,
  43        RC6_MODE_6A,
  44        RC6_MODE_UNKNOWN,
  45};
  46
  47enum rc6_state {
  48        STATE_INACTIVE,
  49        STATE_PREFIX_SPACE,
  50        STATE_HEADER_BIT_START,
  51        STATE_HEADER_BIT_END,
  52        STATE_TOGGLE_START,
  53        STATE_TOGGLE_END,
  54        STATE_BODY_BIT_START,
  55        STATE_BODY_BIT_END,
  56        STATE_FINISHED,
  57};
  58
  59static enum rc6_mode rc6_mode(struct rc6_dec *data)
  60{
  61        switch (data->header & RC6_MODE_MASK) {
  62        case 0:
  63                return RC6_MODE_0;
  64        case 6:
  65                if (!data->toggle)
  66                        return RC6_MODE_6A;
  67                fallthrough;
  68        default:
  69                return RC6_MODE_UNKNOWN;
  70        }
  71}
  72
  73/**
  74 * ir_rc6_decode() - Decode one RC6 pulse or space
  75 * @dev:        the struct rc_dev descriptor of the device
  76 * @ev:         the struct ir_raw_event descriptor of the pulse/space
  77 *
  78 * This function returns -EINVAL if the pulse violates the state machine
  79 */
  80static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
  81{
  82        struct rc6_dec *data = &dev->raw->rc6;
  83        u32 scancode;
  84        u8 toggle;
  85        enum rc_proto protocol;
  86
  87        if (!is_timing_event(ev)) {
  88                if (ev.reset)
  89                        data->state = STATE_INACTIVE;
  90                return 0;
  91        }
  92
  93        if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
  94                goto out;
  95
  96again:
  97        dev_dbg(&dev->dev, "RC6 decode started at state %i (%uus %s)\n",
  98                data->state, ev.duration, TO_STR(ev.pulse));
  99
 100        if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
 101                return 0;
 102
 103        switch (data->state) {
 104
 105        case STATE_INACTIVE:
 106                if (!ev.pulse)
 107                        break;
 108
 109                /* Note: larger margin on first pulse since each RC6_UNIT
 110                   is quite short and some hardware takes some time to
 111                   adjust to the signal */
 112                if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
 113                        break;
 114
 115                data->state = STATE_PREFIX_SPACE;
 116                data->count = 0;
 117                return 0;
 118
 119        case STATE_PREFIX_SPACE:
 120                if (ev.pulse)
 121                        break;
 122
 123                if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
 124                        break;
 125
 126                data->state = STATE_HEADER_BIT_START;
 127                data->header = 0;
 128                return 0;
 129
 130        case STATE_HEADER_BIT_START:
 131                if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
 132                        break;
 133
 134                data->header <<= 1;
 135                if (ev.pulse)
 136                        data->header |= 1;
 137                data->count++;
 138                data->state = STATE_HEADER_BIT_END;
 139                return 0;
 140
 141        case STATE_HEADER_BIT_END:
 142                if (data->count == RC6_HEADER_NBITS)
 143                        data->state = STATE_TOGGLE_START;
 144                else
 145                        data->state = STATE_HEADER_BIT_START;
 146
 147                decrease_duration(&ev, RC6_BIT_END);
 148                goto again;
 149
 150        case STATE_TOGGLE_START:
 151                if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
 152                        break;
 153
 154                data->toggle = ev.pulse;
 155                data->state = STATE_TOGGLE_END;
 156                return 0;
 157
 158        case STATE_TOGGLE_END:
 159                if (!(data->header & RC6_STARTBIT_MASK)) {
 160                        dev_dbg(&dev->dev, "RC6 invalid start bit\n");
 161                        break;
 162                }
 163
 164                data->state = STATE_BODY_BIT_START;
 165                decrease_duration(&ev, RC6_TOGGLE_END);
 166                data->count = 0;
 167                data->body = 0;
 168
 169                switch (rc6_mode(data)) {
 170                case RC6_MODE_0:
 171                        data->wanted_bits = RC6_0_NBITS;
 172                        break;
 173                case RC6_MODE_6A:
 174                        data->wanted_bits = RC6_6A_NBITS;
 175                        break;
 176                default:
 177                        dev_dbg(&dev->dev, "RC6 unknown mode\n");
 178                        goto out;
 179                }
 180                goto again;
 181
 182        case STATE_BODY_BIT_START:
 183                if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
 184                        /* Discard LSB's that won't fit in data->body */
 185                        if (data->count++ < CHAR_BIT * sizeof data->body) {
 186                                data->body <<= 1;
 187                                if (ev.pulse)
 188                                        data->body |= 1;
 189                        }
 190                        data->state = STATE_BODY_BIT_END;
 191                        return 0;
 192                } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
 193                                geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
 194                        data->state = STATE_FINISHED;
 195                        goto again;
 196                }
 197                break;
 198
 199        case STATE_BODY_BIT_END:
 200                if (data->count == data->wanted_bits)
 201                        data->state = STATE_FINISHED;
 202                else
 203                        data->state = STATE_BODY_BIT_START;
 204
 205                decrease_duration(&ev, RC6_BIT_END);
 206                goto again;
 207
 208        case STATE_FINISHED:
 209                if (ev.pulse)
 210                        break;
 211
 212                switch (rc6_mode(data)) {
 213                case RC6_MODE_0:
 214                        scancode = data->body;
 215                        toggle = data->toggle;
 216                        protocol = RC_PROTO_RC6_0;
 217                        dev_dbg(&dev->dev, "RC6(0) scancode 0x%04x (toggle: %u)\n",
 218                                scancode, toggle);
 219                        break;
 220
 221                case RC6_MODE_6A:
 222                        if (data->count > CHAR_BIT * sizeof data->body) {
 223                                dev_dbg(&dev->dev, "RC6 too many (%u) data bits\n",
 224                                        data->count);
 225                                goto out;
 226                        }
 227
 228                        scancode = data->body;
 229                        switch (data->count) {
 230                        case 20:
 231                                protocol = RC_PROTO_RC6_6A_20;
 232                                toggle = 0;
 233                                break;
 234                        case 24:
 235                                protocol = RC_PROTO_RC6_6A_24;
 236                                toggle = 0;
 237                                break;
 238                        case 32:
 239                                switch (scancode & RC6_6A_LCC_MASK) {
 240                                case RC6_6A_MCE_CC:
 241                                case RC6_6A_KATHREIN_CC:
 242                                case RC6_6A_ZOTAC_CC:
 243                                        protocol = RC_PROTO_RC6_MCE;
 244                                        toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
 245                                        scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
 246                                        break;
 247                                default:
 248                                        protocol = RC_PROTO_RC6_6A_32;
 249                                        toggle = 0;
 250                                        break;
 251                                }
 252                                break;
 253                        default:
 254                                dev_dbg(&dev->dev, "RC6(6A) unsupported length\n");
 255                                goto out;
 256                        }
 257
 258                        dev_dbg(&dev->dev, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
 259                                protocol, scancode, toggle);
 260                        break;
 261                default:
 262                        dev_dbg(&dev->dev, "RC6 unknown mode\n");
 263                        goto out;
 264                }
 265
 266                rc_keydown(dev, protocol, scancode, toggle);
 267                data->state = STATE_INACTIVE;
 268                return 0;
 269        }
 270
 271out:
 272        dev_dbg(&dev->dev, "RC6 decode failed at state %i (%uus %s)\n",
 273                data->state, ev.duration, TO_STR(ev.pulse));
 274        data->state = STATE_INACTIVE;
 275        return -EINVAL;
 276}
 277
 278static const struct ir_raw_timings_manchester ir_rc6_timings[4] = {
 279        {
 280                .leader_pulse           = RC6_PREFIX_PULSE,
 281                .leader_space           = RC6_PREFIX_SPACE,
 282                .clock                  = RC6_UNIT,
 283                .invert                 = 1,
 284        },
 285        {
 286                .clock                  = RC6_UNIT * 2,
 287                .invert                 = 1,
 288        },
 289        {
 290                .clock                  = RC6_UNIT,
 291                .invert                 = 1,
 292                .trailer_space          = RC6_SUFFIX_SPACE,
 293        },
 294};
 295
 296/**
 297 * ir_rc6_encode() - Encode a scancode as a stream of raw events
 298 *
 299 * @protocol:   protocol to encode
 300 * @scancode:   scancode to encode
 301 * @events:     array of raw ir events to write into
 302 * @max:        maximum size of @events
 303 *
 304 * Returns:     The number of events written.
 305 *              -ENOBUFS if there isn't enough space in the array to fit the
 306 *              encoding. In this case all @max events will have been written.
 307 *              -EINVAL if the scancode is ambiguous or invalid.
 308 */
 309static int ir_rc6_encode(enum rc_proto protocol, u32 scancode,
 310                         struct ir_raw_event *events, unsigned int max)
 311{
 312        int ret;
 313        struct ir_raw_event *e = events;
 314
 315        if (protocol == RC_PROTO_RC6_0) {
 316                /* Modulate the header (Start Bit & Mode-0) */
 317                ret = ir_raw_gen_manchester(&e, max - (e - events),
 318                                            &ir_rc6_timings[0],
 319                                            RC6_HEADER_NBITS, (1 << 3));
 320                if (ret < 0)
 321                        return ret;
 322
 323                /* Modulate Trailer Bit */
 324                ret = ir_raw_gen_manchester(&e, max - (e - events),
 325                                            &ir_rc6_timings[1], 1, 0);
 326                if (ret < 0)
 327                        return ret;
 328
 329                /* Modulate rest of the data */
 330                ret = ir_raw_gen_manchester(&e, max - (e - events),
 331                                            &ir_rc6_timings[2], RC6_0_NBITS,
 332                                            scancode);
 333                if (ret < 0)
 334                        return ret;
 335
 336        } else {
 337                int bits;
 338
 339                switch (protocol) {
 340                case RC_PROTO_RC6_MCE:
 341                case RC_PROTO_RC6_6A_32:
 342                        bits = 32;
 343                        break;
 344                case RC_PROTO_RC6_6A_24:
 345                        bits = 24;
 346                        break;
 347                case RC_PROTO_RC6_6A_20:
 348                        bits = 20;
 349                        break;
 350                default:
 351                        return -EINVAL;
 352                }
 353
 354                /* Modulate the header (Start Bit & Header-version 6 */
 355                ret = ir_raw_gen_manchester(&e, max - (e - events),
 356                                            &ir_rc6_timings[0],
 357                                            RC6_HEADER_NBITS, (1 << 3 | 6));
 358                if (ret < 0)
 359                        return ret;
 360
 361                /* Modulate Trailer Bit */
 362                ret = ir_raw_gen_manchester(&e, max - (e - events),
 363                                            &ir_rc6_timings[1], 1, 0);
 364                if (ret < 0)
 365                        return ret;
 366
 367                /* Modulate rest of the data */
 368                ret = ir_raw_gen_manchester(&e, max - (e - events),
 369                                            &ir_rc6_timings[2],
 370                                            bits,
 371                                            scancode);
 372                if (ret < 0)
 373                        return ret;
 374        }
 375
 376        return e - events;
 377}
 378
 379static struct ir_raw_handler rc6_handler = {
 380        .protocols      = RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 |
 381                          RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 |
 382                          RC_PROTO_BIT_RC6_MCE,
 383        .decode         = ir_rc6_decode,
 384        .encode         = ir_rc6_encode,
 385        .carrier        = 36000,
 386        .min_timeout    = RC6_SUFFIX_SPACE,
 387};
 388
 389static int __init ir_rc6_decode_init(void)
 390{
 391        ir_raw_handler_register(&rc6_handler);
 392
 393        printk(KERN_INFO "IR RC6 protocol handler initialized\n");
 394        return 0;
 395}
 396
 397static void __exit ir_rc6_decode_exit(void)
 398{
 399        ir_raw_handler_unregister(&rc6_handler);
 400}
 401
 402module_init(ir_rc6_decode_init);
 403module_exit(ir_rc6_decode_exit);
 404
 405MODULE_LICENSE("GPL");
 406MODULE_AUTHOR("David H\xC3\xA4rdeman <david@hardeman.nu>");
 407MODULE_DESCRIPTION("RC6 IR protocol decoder");
 408