linux/drivers/media/IR/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 "ir-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        (8  * 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
  30/* Used to register nec_decoder clients */
  31static LIST_HEAD(decoder_list);
  32static DEFINE_SPINLOCK(decoder_lock);
  33
  34enum nec_state {
  35        STATE_INACTIVE,
  36        STATE_HEADER_SPACE,
  37        STATE_BIT_PULSE,
  38        STATE_BIT_SPACE,
  39        STATE_TRAILER_PULSE,
  40        STATE_TRAILER_SPACE,
  41};
  42
  43struct decoder_data {
  44        struct list_head        list;
  45        struct ir_input_dev     *ir_dev;
  46        int                     enabled:1;
  47
  48        /* State machine control */
  49        enum nec_state          state;
  50        u32                     nec_bits;
  51        unsigned                count;
  52};
  53
  54
  55/**
  56 * get_decoder_data()   - gets decoder data
  57 * @input_dev:  input device
  58 *
  59 * Returns the struct decoder_data that corresponds to a device
  60 */
  61static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
  62{
  63        struct decoder_data *data = NULL;
  64
  65        spin_lock(&decoder_lock);
  66        list_for_each_entry(data, &decoder_list, list) {
  67                if (data->ir_dev == ir_dev)
  68                        break;
  69        }
  70        spin_unlock(&decoder_lock);
  71        return data;
  72}
  73
  74static ssize_t store_enabled(struct device *d,
  75                             struct device_attribute *mattr,
  76                             const char *buf,
  77                             size_t len)
  78{
  79        unsigned long value;
  80        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  81        struct decoder_data *data = get_decoder_data(ir_dev);
  82
  83        if (!data)
  84                return -EINVAL;
  85
  86        if (strict_strtoul(buf, 10, &value) || value > 1)
  87                return -EINVAL;
  88
  89        data->enabled = value;
  90
  91        return len;
  92}
  93
  94static ssize_t show_enabled(struct device *d,
  95                             struct device_attribute *mattr, char *buf)
  96{
  97        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  98        struct decoder_data *data = get_decoder_data(ir_dev);
  99
 100        if (!data)
 101                return -EINVAL;
 102
 103        if (data->enabled)
 104                return sprintf(buf, "1\n");
 105        else
 106        return sprintf(buf, "0\n");
 107}
 108
 109static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
 110
 111static struct attribute *decoder_attributes[] = {
 112        &dev_attr_enabled.attr,
 113        NULL
 114};
 115
 116static struct attribute_group decoder_attribute_group = {
 117        .name   = "nec_decoder",
 118        .attrs  = decoder_attributes,
 119};
 120
 121/**
 122 * ir_nec_decode() - Decode one NEC pulse or space
 123 * @input_dev:  the struct input_dev descriptor of the device
 124 * @duration:   the struct ir_raw_event descriptor of the pulse/space
 125 *
 126 * This function returns -EINVAL if the pulse violates the state machine
 127 */
 128static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 129{
 130        struct decoder_data *data;
 131        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 132        u32 scancode;
 133        u8 address, not_address, command, not_command;
 134
 135        data = get_decoder_data(ir_dev);
 136        if (!data)
 137                return -EINVAL;
 138
 139        if (!data->enabled)
 140                return 0;
 141
 142        if (IS_RESET(ev)) {
 143                data->state = STATE_INACTIVE;
 144                return 0;
 145        }
 146
 147        IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
 148                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 149
 150        switch (data->state) {
 151
 152        case STATE_INACTIVE:
 153                if (!ev.pulse)
 154                        break;
 155
 156                if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) &&
 157                    !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
 158                        break;
 159
 160                data->count = 0;
 161                data->state = STATE_HEADER_SPACE;
 162                return 0;
 163
 164        case STATE_HEADER_SPACE:
 165                if (ev.pulse)
 166                        break;
 167
 168                if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
 169                        data->state = STATE_BIT_PULSE;
 170                        return 0;
 171                } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
 172                        ir_repeat(input_dev);
 173                        IR_dprintk(1, "Repeat last key\n");
 174                        data->state = STATE_TRAILER_PULSE;
 175                        return 0;
 176                }
 177
 178                break;
 179
 180        case STATE_BIT_PULSE:
 181                if (!ev.pulse)
 182                        break;
 183
 184                if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
 185                        break;
 186
 187                data->state = STATE_BIT_SPACE;
 188                return 0;
 189
 190        case STATE_BIT_SPACE:
 191                if (ev.pulse)
 192                        break;
 193
 194                data->nec_bits <<= 1;
 195                if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
 196                        data->nec_bits |= 1;
 197                else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
 198                        break;
 199                data->count++;
 200
 201                if (data->count == NEC_NBITS)
 202                        data->state = STATE_TRAILER_PULSE;
 203                else
 204                        data->state = STATE_BIT_PULSE;
 205
 206                return 0;
 207
 208        case STATE_TRAILER_PULSE:
 209                if (!ev.pulse)
 210                        break;
 211
 212                if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
 213                        break;
 214
 215                data->state = STATE_TRAILER_SPACE;
 216                return 0;
 217
 218        case STATE_TRAILER_SPACE:
 219                if (ev.pulse)
 220                        break;
 221
 222                if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
 223                        break;
 224
 225                address     = bitrev8((data->nec_bits >> 24) & 0xff);
 226                not_address = bitrev8((data->nec_bits >> 16) & 0xff);
 227                command     = bitrev8((data->nec_bits >>  8) & 0xff);
 228                not_command = bitrev8((data->nec_bits >>  0) & 0xff);
 229
 230                if ((command ^ not_command) != 0xff) {
 231                        IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
 232                                   data->nec_bits);
 233                        break;
 234                }
 235
 236                if ((address ^ not_address) != 0xff) {
 237                        /* Extended NEC */
 238                        scancode = address     << 16 |
 239                                   not_address <<  8 |
 240                                   command;
 241                        IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
 242                } else {
 243                        /* Normal NEC */
 244                        scancode = address << 8 | command;
 245                        IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
 246                }
 247
 248                ir_keydown(input_dev, scancode, 0);
 249                data->state = STATE_INACTIVE;
 250                return 0;
 251        }
 252
 253        IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
 254                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 255        data->state = STATE_INACTIVE;
 256        return -EINVAL;
 257}
 258
 259static int ir_nec_register(struct input_dev *input_dev)
 260{
 261        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 262        struct decoder_data *data;
 263        int rc;
 264
 265        rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 266        if (rc < 0)
 267                return rc;
 268
 269        data = kzalloc(sizeof(*data), GFP_KERNEL);
 270        if (!data) {
 271                sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 272                return -ENOMEM;
 273        }
 274
 275        data->ir_dev = ir_dev;
 276        data->enabled = 1;
 277
 278        spin_lock(&decoder_lock);
 279        list_add_tail(&data->list, &decoder_list);
 280        spin_unlock(&decoder_lock);
 281
 282        return 0;
 283}
 284
 285static int ir_nec_unregister(struct input_dev *input_dev)
 286{
 287        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 288        static struct decoder_data *data;
 289
 290        data = get_decoder_data(ir_dev);
 291        if (!data)
 292                return 0;
 293
 294        sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 295
 296        spin_lock(&decoder_lock);
 297        list_del(&data->list);
 298        spin_unlock(&decoder_lock);
 299
 300        return 0;
 301}
 302
 303static struct ir_raw_handler nec_handler = {
 304        .decode         = ir_nec_decode,
 305        .raw_register   = ir_nec_register,
 306        .raw_unregister = ir_nec_unregister,
 307};
 308
 309static int __init ir_nec_decode_init(void)
 310{
 311        ir_raw_handler_register(&nec_handler);
 312
 313        printk(KERN_INFO "IR NEC protocol handler initialized\n");
 314        return 0;
 315}
 316
 317static void __exit ir_nec_decode_exit(void)
 318{
 319        ir_raw_handler_unregister(&nec_handler);
 320}
 321
 322module_init(ir_nec_decode_init);
 323module_exit(ir_nec_decode_exit);
 324
 325MODULE_LICENSE("GPL");
 326MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 327MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
 328MODULE_DESCRIPTION("NEC IR protocol decoder");
 329