linux/drivers/media/rc/ir-nec-decoder.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
   3//
   4// Copyright (C) 2010 by Mauro Carvalho Chehab
   5
   6#include <linux/bitrev.h>
   7#include <linux/module.h>
   8#include "rc-core-priv.h"
   9
  10#define NEC_NBITS               32
  11#define NEC_UNIT                562500  /* ns */
  12#define NEC_HEADER_PULSE        (16 * NEC_UNIT)
  13#define NECX_HEADER_PULSE       (8  * NEC_UNIT) /* Less common NEC variant */
  14#define NEC_HEADER_SPACE        (8  * NEC_UNIT)
  15#define NEC_REPEAT_SPACE        (4  * NEC_UNIT)
  16#define NEC_BIT_PULSE           (1  * NEC_UNIT)
  17#define NEC_BIT_0_SPACE         (1  * NEC_UNIT)
  18#define NEC_BIT_1_SPACE         (3  * NEC_UNIT)
  19#define NEC_TRAILER_PULSE       (1  * NEC_UNIT)
  20#define NEC_TRAILER_SPACE       (10 * NEC_UNIT) /* even longer in reality */
  21#define NECX_REPEAT_BITS        1
  22
  23enum nec_state {
  24        STATE_INACTIVE,
  25        STATE_HEADER_SPACE,
  26        STATE_BIT_PULSE,
  27        STATE_BIT_SPACE,
  28        STATE_TRAILER_PULSE,
  29        STATE_TRAILER_SPACE,
  30};
  31
  32/**
  33 * ir_nec_decode() - Decode one NEC pulse or space
  34 * @dev:        the struct rc_dev descriptor of the device
  35 * @ev:         the struct ir_raw_event descriptor of the pulse/space
  36 *
  37 * This function returns -EINVAL if the pulse violates the state machine
  38 */
  39static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
  40{
  41        struct nec_dec *data = &dev->raw->nec;
  42        u32 scancode;
  43        enum rc_proto rc_proto;
  44        u8 address, not_address, command, not_command;
  45
  46        if (!is_timing_event(ev)) {
  47                if (ev.reset)
  48                        data->state = STATE_INACTIVE;
  49                return 0;
  50        }
  51
  52        dev_dbg(&dev->dev, "NEC decode started at state %d (%uus %s)\n",
  53                data->state, TO_US(ev.duration), TO_STR(ev.pulse));
  54
  55        switch (data->state) {
  56
  57        case STATE_INACTIVE:
  58                if (!ev.pulse)
  59                        break;
  60
  61                if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) {
  62                        data->is_nec_x = false;
  63                        data->necx_repeat = false;
  64                } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
  65                        data->is_nec_x = true;
  66                else
  67                        break;
  68
  69                data->count = 0;
  70                data->state = STATE_HEADER_SPACE;
  71                return 0;
  72
  73        case STATE_HEADER_SPACE:
  74                if (ev.pulse)
  75                        break;
  76
  77                if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) {
  78                        data->state = STATE_BIT_PULSE;
  79                        return 0;
  80                } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
  81                        data->state = STATE_TRAILER_PULSE;
  82                        return 0;
  83                }
  84
  85                break;
  86
  87        case STATE_BIT_PULSE:
  88                if (!ev.pulse)
  89                        break;
  90
  91                if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
  92                        break;
  93
  94                data->state = STATE_BIT_SPACE;
  95                return 0;
  96
  97        case STATE_BIT_SPACE:
  98                if (ev.pulse)
  99                        break;
 100
 101                if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
 102                    geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
 103                        dev_dbg(&dev->dev, "Repeat last key\n");
 104                        rc_repeat(dev);
 105                        data->state = STATE_INACTIVE;
 106                        return 0;
 107                } else if (data->count > NECX_REPEAT_BITS)
 108                        data->necx_repeat = false;
 109
 110                data->bits <<= 1;
 111                if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
 112                        data->bits |= 1;
 113                else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
 114                        break;
 115                data->count++;
 116
 117                if (data->count == NEC_NBITS)
 118                        data->state = STATE_TRAILER_PULSE;
 119                else
 120                        data->state = STATE_BIT_PULSE;
 121
 122                return 0;
 123
 124        case STATE_TRAILER_PULSE:
 125                if (!ev.pulse)
 126                        break;
 127
 128                if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
 129                        break;
 130
 131                data->state = STATE_TRAILER_SPACE;
 132                return 0;
 133
 134        case STATE_TRAILER_SPACE:
 135                if (ev.pulse)
 136                        break;
 137
 138                if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
 139                        break;
 140
 141                if (data->count == NEC_NBITS) {
 142                        address     = bitrev8((data->bits >> 24) & 0xff);
 143                        not_address = bitrev8((data->bits >> 16) & 0xff);
 144                        command     = bitrev8((data->bits >>  8) & 0xff);
 145                        not_command = bitrev8((data->bits >>  0) & 0xff);
 146
 147                        scancode = ir_nec_bytes_to_scancode(address,
 148                                                            not_address,
 149                                                            command,
 150                                                            not_command,
 151                                                            &rc_proto);
 152
 153                        if (data->is_nec_x)
 154                                data->necx_repeat = true;
 155
 156                        rc_keydown(dev, rc_proto, scancode, 0);
 157                } else {
 158                        rc_repeat(dev);
 159                }
 160
 161                data->state = STATE_INACTIVE;
 162                return 0;
 163        }
 164
 165        dev_dbg(&dev->dev, "NEC decode failed at count %d state %d (%uus %s)\n",
 166                data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 167        data->state = STATE_INACTIVE;
 168        return -EINVAL;
 169}
 170
 171/**
 172 * ir_nec_scancode_to_raw() - encode an NEC scancode ready for modulation.
 173 * @protocol:   specific protocol to use
 174 * @scancode:   a single NEC scancode.
 175 */
 176static u32 ir_nec_scancode_to_raw(enum rc_proto protocol, u32 scancode)
 177{
 178        unsigned int addr, addr_inv, data, data_inv;
 179
 180        data = scancode & 0xff;
 181
 182        if (protocol == RC_PROTO_NEC32) {
 183                /* 32-bit NEC (used by Apple and TiVo remotes) */
 184                /* scan encoding: aaAAddDD */
 185                addr_inv   = (scancode >> 24) & 0xff;
 186                addr       = (scancode >> 16) & 0xff;
 187                data_inv   = (scancode >>  8) & 0xff;
 188        } else if (protocol == RC_PROTO_NECX) {
 189                /* Extended NEC */
 190                /* scan encoding AAaaDD */
 191                addr       = (scancode >> 16) & 0xff;
 192                addr_inv   = (scancode >>  8) & 0xff;
 193                data_inv   = data ^ 0xff;
 194        } else {
 195                /* Normal NEC */
 196                /* scan encoding: AADD */
 197                addr       = (scancode >>  8) & 0xff;
 198                addr_inv   = addr ^ 0xff;
 199                data_inv   = data ^ 0xff;
 200        }
 201
 202        /* raw encoding: ddDDaaAA */
 203        return data_inv << 24 |
 204               data     << 16 |
 205               addr_inv <<  8 |
 206               addr;
 207}
 208
 209static const struct ir_raw_timings_pd ir_nec_timings = {
 210        .header_pulse   = NEC_HEADER_PULSE,
 211        .header_space   = NEC_HEADER_SPACE,
 212        .bit_pulse      = NEC_BIT_PULSE,
 213        .bit_space[0]   = NEC_BIT_0_SPACE,
 214        .bit_space[1]   = NEC_BIT_1_SPACE,
 215        .trailer_pulse  = NEC_TRAILER_PULSE,
 216        .trailer_space  = NEC_TRAILER_SPACE,
 217        .msb_first      = 0,
 218};
 219
 220/**
 221 * ir_nec_encode() - Encode a scancode as a stream of raw events
 222 *
 223 * @protocol:   protocol to encode
 224 * @scancode:   scancode to encode
 225 * @events:     array of raw ir events to write into
 226 * @max:        maximum size of @events
 227 *
 228 * Returns:     The number of events written.
 229 *              -ENOBUFS if there isn't enough space in the array to fit the
 230 *              encoding. In this case all @max events will have been written.
 231 */
 232static int ir_nec_encode(enum rc_proto protocol, u32 scancode,
 233                         struct ir_raw_event *events, unsigned int max)
 234{
 235        struct ir_raw_event *e = events;
 236        int ret;
 237        u32 raw;
 238
 239        /* Convert a NEC scancode to raw NEC data */
 240        raw = ir_nec_scancode_to_raw(protocol, scancode);
 241
 242        /* Modulate the raw data using a pulse distance modulation */
 243        ret = ir_raw_gen_pd(&e, max, &ir_nec_timings, NEC_NBITS, raw);
 244        if (ret < 0)
 245                return ret;
 246
 247        return e - events;
 248}
 249
 250static struct ir_raw_handler nec_handler = {
 251        .protocols      = RC_PROTO_BIT_NEC | RC_PROTO_BIT_NECX |
 252                                                        RC_PROTO_BIT_NEC32,
 253        .decode         = ir_nec_decode,
 254        .encode         = ir_nec_encode,
 255        .carrier        = 38000,
 256        .min_timeout    = NEC_TRAILER_SPACE,
 257};
 258
 259static int __init ir_nec_decode_init(void)
 260{
 261        ir_raw_handler_register(&nec_handler);
 262
 263        printk(KERN_INFO "IR NEC protocol handler initialized\n");
 264        return 0;
 265}
 266
 267static void __exit ir_nec_decode_exit(void)
 268{
 269        ir_raw_handler_unregister(&nec_handler);
 270}
 271
 272module_init(ir_nec_decode_init);
 273module_exit(ir_nec_decode_exit);
 274
 275MODULE_LICENSE("GPL v2");
 276MODULE_AUTHOR("Mauro Carvalho Chehab");
 277MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 278MODULE_DESCRIPTION("NEC IR protocol decoder");
 279