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