linux/drivers/media/rc/ir-nec-decoder.c
<<
>>
Prefs
   1/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
   2 *
   3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
   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 <linux/bitrev.h>
  16#include "rc-core-priv.h"
  17
  18#define NEC_NBITS               32
  19#define NEC_UNIT                562500  /* ns */
  20#define NEC_HEADER_PULSE        (16 * NEC_UNIT)
  21#define NECX_HEADER_PULSE       (8  * NEC_UNIT) /* Less common NEC variant */
  22#define NEC_HEADER_SPACE        (8  * NEC_UNIT)
  23#define NEC_REPEAT_SPACE        (4  * NEC_UNIT)
  24#define NEC_BIT_PULSE           (1  * NEC_UNIT)
  25#define NEC_BIT_0_SPACE         (1  * NEC_UNIT)
  26#define NEC_BIT_1_SPACE         (3  * NEC_UNIT)
  27#define NEC_TRAILER_PULSE       (1  * NEC_UNIT)
  28#define NEC_TRAILER_SPACE       (10 * NEC_UNIT) /* even longer in reality */
  29#define NECX_REPEAT_BITS        1
  30
  31enum nec_state {
  32        STATE_INACTIVE,
  33        STATE_HEADER_SPACE,
  34        STATE_BIT_PULSE,
  35        STATE_BIT_SPACE,
  36        STATE_TRAILER_PULSE,
  37        STATE_TRAILER_SPACE,
  38};
  39
  40/**
  41 * ir_nec_decode() - Decode one NEC pulse or space
  42 * @dev:        the struct rc_dev descriptor of the device
  43 * @duration:   the struct ir_raw_event descriptor of the pulse/space
  44 *
  45 * This function returns -EINVAL if the pulse violates the state machine
  46 */
  47static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
  48{
  49        struct nec_dec *data = &dev->raw->nec;
  50        u32 scancode;
  51        u8 address, not_address, command, not_command;
  52
  53        if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
  54                return 0;
  55
  56        if (!is_timing_event(ev)) {
  57                if (ev.reset)
  58                        data->state = STATE_INACTIVE;
  59                return 0;
  60        }
  61
  62        IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
  63                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
  64
  65        switch (data->state) {
  66
  67        case STATE_INACTIVE:
  68                if (!ev.pulse)
  69                        break;
  70
  71                if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
  72                        data->is_nec_x = false;
  73                        data->necx_repeat = false;
  74                } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
  75                        data->is_nec_x = true;
  76                else
  77                        break;
  78
  79                data->count = 0;
  80                data->state = STATE_HEADER_SPACE;
  81                return 0;
  82
  83        case STATE_HEADER_SPACE:
  84                if (ev.pulse)
  85                        break;
  86
  87                if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
  88                        data->state = STATE_BIT_PULSE;
  89                        return 0;
  90                } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
  91                        if (!dev->keypressed) {
  92                                IR_dprintk(1, "Discarding last key repeat: event after key up\n");
  93                        } else {
  94                                rc_repeat(dev);
  95                                IR_dprintk(1, "Repeat last key\n");
  96                                data->state = STATE_TRAILER_PULSE;
  97                        }
  98                        return 0;
  99                }
 100
 101                break;
 102
 103        case STATE_BIT_PULSE:
 104                if (!ev.pulse)
 105                        break;
 106
 107                if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
 108                        break;
 109
 110                data->state = STATE_BIT_SPACE;
 111                return 0;
 112
 113        case STATE_BIT_SPACE:
 114                if (ev.pulse)
 115                        break;
 116
 117                if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
 118                        geq_margin(ev.duration,
 119                        NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
 120                                IR_dprintk(1, "Repeat last key\n");
 121                                rc_repeat(dev);
 122                                data->state = STATE_INACTIVE;
 123                                return 0;
 124
 125                } else if (data->count > NECX_REPEAT_BITS)
 126                        data->necx_repeat = false;
 127
 128                data->bits <<= 1;
 129                if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
 130                        data->bits |= 1;
 131                else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
 132                        break;
 133                data->count++;
 134
 135                if (data->count == NEC_NBITS)
 136                        data->state = STATE_TRAILER_PULSE;
 137                else
 138                        data->state = STATE_BIT_PULSE;
 139
 140                return 0;
 141
 142        case STATE_TRAILER_PULSE:
 143                if (!ev.pulse)
 144                        break;
 145
 146                if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
 147                        break;
 148
 149                data->state = STATE_TRAILER_SPACE;
 150                return 0;
 151
 152        case STATE_TRAILER_SPACE:
 153                if (ev.pulse)
 154                        break;
 155
 156                if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
 157                        break;
 158
 159                address     = bitrev8((data->bits >> 24) & 0xff);
 160                not_address = bitrev8((data->bits >> 16) & 0xff);
 161                command     = bitrev8((data->bits >>  8) & 0xff);
 162                not_command = bitrev8((data->bits >>  0) & 0xff);
 163
 164                if ((command ^ not_command) != 0xff) {
 165                        IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
 166                                   data->bits);
 167                        break;
 168                }
 169
 170                if ((address ^ not_address) != 0xff) {
 171                        /* Extended NEC */
 172                        scancode = address     << 16 |
 173                                   not_address <<  8 |
 174                                   command;
 175                        IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
 176                } else {
 177                        /* Normal NEC */
 178                        scancode = address << 8 | command;
 179                        IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
 180                }
 181
 182                if (data->is_nec_x)
 183                        data->necx_repeat = true;
 184
 185                rc_keydown(dev, scancode, 0);
 186                data->state = STATE_INACTIVE;
 187                return 0;
 188        }
 189
 190        IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
 191                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 192        data->state = STATE_INACTIVE;
 193        return -EINVAL;
 194}
 195
 196static struct ir_raw_handler nec_handler = {
 197        .protocols      = RC_TYPE_NEC,
 198        .decode         = ir_nec_decode,
 199};
 200
 201static int __init ir_nec_decode_init(void)
 202{
 203        ir_raw_handler_register(&nec_handler);
 204
 205        printk(KERN_INFO "IR NEC protocol handler initialized\n");
 206        return 0;
 207}
 208
 209static void __exit ir_nec_decode_exit(void)
 210{
 211        ir_raw_handler_unregister(&nec_handler);
 212}
 213
 214module_init(ir_nec_decode_init);
 215module_exit(ir_nec_decode_exit);
 216
 217MODULE_LICENSE("GPL");
 218MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 219MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 220MODULE_DESCRIPTION("NEC IR protocol decoder");
 221