linux/drivers/media/IR/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\xC3\xA4rdeman <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 "ir-core-priv.h"
  16
  17/*
  18 * This decoder currently supports:
  19 * RC6-0-16     (standard toggle bit in header)
  20 * RC6-6A-24    (no toggle bit)
  21 * RC6-6A-32    (MCE version with toggle bit in body)
  22 */
  23
  24#define RC6_UNIT                444444  /* us */
  25#define RC6_HEADER_NBITS        4       /* not including toggle bit */
  26#define RC6_0_NBITS             16
  27#define RC6_6A_SMALL_NBITS      24
  28#define RC6_6A_LARGE_NBITS      32
  29#define RC6_PREFIX_PULSE        (6 * RC6_UNIT)
  30#define RC6_PREFIX_SPACE        (2 * RC6_UNIT)
  31#define RC6_BIT_START           (1 * RC6_UNIT)
  32#define RC6_BIT_END             (1 * RC6_UNIT)
  33#define RC6_TOGGLE_START        (2 * RC6_UNIT)
  34#define RC6_TOGGLE_END          (2 * RC6_UNIT)
  35#define RC6_MODE_MASK           0x07    /* for the header bits */
  36#define RC6_STARTBIT_MASK       0x08    /* for the header bits */
  37#define RC6_6A_MCE_TOGGLE_MASK  0x8000  /* for the body bits */
  38
  39/* Used to register rc6_decoder clients */
  40static LIST_HEAD(decoder_list);
  41static DEFINE_SPINLOCK(decoder_lock);
  42
  43enum rc6_mode {
  44        RC6_MODE_0,
  45        RC6_MODE_6A,
  46        RC6_MODE_UNKNOWN,
  47};
  48
  49enum rc6_state {
  50        STATE_INACTIVE,
  51        STATE_PREFIX_SPACE,
  52        STATE_HEADER_BIT_START,
  53        STATE_HEADER_BIT_END,
  54        STATE_TOGGLE_START,
  55        STATE_TOGGLE_END,
  56        STATE_BODY_BIT_START,
  57        STATE_BODY_BIT_END,
  58        STATE_FINISHED,
  59};
  60
  61struct decoder_data {
  62        struct list_head        list;
  63        struct ir_input_dev     *ir_dev;
  64        int                     enabled:1;
  65
  66        /* State machine control */
  67        enum rc6_state          state;
  68        u8                      header;
  69        u32                     body;
  70        struct ir_raw_event     prev_ev;
  71        bool                    toggle;
  72        unsigned                count;
  73        unsigned                wanted_bits;
  74};
  75
  76
  77/**
  78 * get_decoder_data()   - gets decoder data
  79 * @input_dev:  input device
  80 *
  81 * Returns the struct decoder_data that corresponds to a device
  82 */
  83static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
  84{
  85        struct decoder_data *data = NULL;
  86
  87        spin_lock(&decoder_lock);
  88        list_for_each_entry(data, &decoder_list, list) {
  89                if (data->ir_dev == ir_dev)
  90                        break;
  91        }
  92        spin_unlock(&decoder_lock);
  93        return data;
  94}
  95
  96static ssize_t store_enabled(struct device *d,
  97                             struct device_attribute *mattr,
  98                             const char *buf,
  99                             size_t len)
 100{
 101        unsigned long value;
 102        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
 103        struct decoder_data *data = get_decoder_data(ir_dev);
 104
 105        if (!data)
 106                return -EINVAL;
 107
 108        if (strict_strtoul(buf, 10, &value) || value > 1)
 109                return -EINVAL;
 110
 111        data->enabled = value;
 112
 113        return len;
 114}
 115
 116static ssize_t show_enabled(struct device *d,
 117                             struct device_attribute *mattr, char *buf)
 118{
 119        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
 120        struct decoder_data *data = get_decoder_data(ir_dev);
 121
 122        if (!data)
 123                return -EINVAL;
 124
 125        if (data->enabled)
 126                return sprintf(buf, "1\n");
 127        else
 128        return sprintf(buf, "0\n");
 129}
 130
 131static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
 132
 133static struct attribute *decoder_attributes[] = {
 134        &dev_attr_enabled.attr,
 135        NULL
 136};
 137
 138static struct attribute_group decoder_attribute_group = {
 139        .name   = "rc6_decoder",
 140        .attrs  = decoder_attributes,
 141};
 142
 143static enum rc6_mode rc6_mode(struct decoder_data *data) {
 144        switch (data->header & RC6_MODE_MASK) {
 145        case 0:
 146                return RC6_MODE_0;
 147        case 6:
 148                if (!data->toggle)
 149                        return RC6_MODE_6A;
 150                /* fall through */
 151        default:
 152                return RC6_MODE_UNKNOWN;
 153        }
 154}
 155
 156/**
 157 * ir_rc6_decode() - Decode one RC6 pulse or space
 158 * @input_dev:  the struct input_dev descriptor of the device
 159 * @ev:         the struct ir_raw_event descriptor of the pulse/space
 160 *
 161 * This function returns -EINVAL if the pulse violates the state machine
 162 */
 163static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 164{
 165        struct decoder_data *data;
 166        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 167        u32 scancode;
 168        u8 toggle;
 169
 170        data = get_decoder_data(ir_dev);
 171        if (!data)
 172                return -EINVAL;
 173
 174        if (!data->enabled)
 175                return 0;
 176
 177        if (IS_RESET(ev)) {
 178                data->state = STATE_INACTIVE;
 179                return 0;
 180        }
 181
 182        if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
 183                goto out;
 184
 185again:
 186        IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
 187                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 188
 189        if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
 190                return 0;
 191
 192        switch (data->state) {
 193
 194        case STATE_INACTIVE:
 195                if (!ev.pulse)
 196                        break;
 197
 198                /* Note: larger margin on first pulse since each RC6_UNIT
 199                   is quite short and some hardware takes some time to
 200                   adjust to the signal */
 201                if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
 202                        break;
 203
 204                data->state = STATE_PREFIX_SPACE;
 205                data->count = 0;
 206                return 0;
 207
 208        case STATE_PREFIX_SPACE:
 209                if (ev.pulse)
 210                        break;
 211
 212                if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
 213                        break;
 214
 215                data->state = STATE_HEADER_BIT_START;
 216                return 0;
 217
 218        case STATE_HEADER_BIT_START:
 219                if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
 220                        break;
 221
 222                data->header <<= 1;
 223                if (ev.pulse)
 224                        data->header |= 1;
 225                data->count++;
 226                data->prev_ev = ev;
 227                data->state = STATE_HEADER_BIT_END;
 228                return 0;
 229
 230        case STATE_HEADER_BIT_END:
 231                if (!is_transition(&ev, &data->prev_ev))
 232                        break;
 233
 234                if (data->count == RC6_HEADER_NBITS)
 235                        data->state = STATE_TOGGLE_START;
 236                else
 237                        data->state = STATE_HEADER_BIT_START;
 238
 239                decrease_duration(&ev, RC6_BIT_END);
 240                goto again;
 241
 242        case STATE_TOGGLE_START:
 243                if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
 244                        break;
 245
 246                data->toggle = ev.pulse;
 247                data->prev_ev = ev;
 248                data->state = STATE_TOGGLE_END;
 249                return 0;
 250
 251        case STATE_TOGGLE_END:
 252                if (!is_transition(&ev, &data->prev_ev) ||
 253                    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
 254                        break;
 255
 256                if (!(data->header & RC6_STARTBIT_MASK)) {
 257                        IR_dprintk(1, "RC6 invalid start bit\n");
 258                        break;
 259                }
 260
 261                data->state = STATE_BODY_BIT_START;
 262                data->prev_ev = ev;
 263                decrease_duration(&ev, RC6_TOGGLE_END);
 264                data->count = 0;
 265
 266                switch (rc6_mode(data)) {
 267                case RC6_MODE_0:
 268                        data->wanted_bits = RC6_0_NBITS;
 269                        break;
 270                case RC6_MODE_6A:
 271                        /* This might look weird, but we basically
 272                           check the value of the first body bit to
 273                           determine the number of bits in mode 6A */
 274                        if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
 275                            geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
 276                                data->wanted_bits = RC6_6A_LARGE_NBITS;
 277                        else
 278                                data->wanted_bits = RC6_6A_SMALL_NBITS;
 279                        break;
 280                default:
 281                        IR_dprintk(1, "RC6 unknown mode\n");
 282                        goto out;
 283                }
 284                goto again;
 285
 286        case STATE_BODY_BIT_START:
 287                if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
 288                        break;
 289
 290                data->body <<= 1;
 291                if (ev.pulse)
 292                        data->body |= 1;
 293                data->count++;
 294                data->prev_ev = ev;
 295
 296                data->state = STATE_BODY_BIT_END;
 297                return 0;
 298
 299        case STATE_BODY_BIT_END:
 300                if (!is_transition(&ev, &data->prev_ev))
 301                        break;
 302
 303                if (data->count == data->wanted_bits)
 304                        data->state = STATE_FINISHED;
 305                else
 306                        data->state = STATE_BODY_BIT_START;
 307
 308                decrease_duration(&ev, RC6_BIT_END);
 309                goto again;
 310
 311        case STATE_FINISHED:
 312                if (ev.pulse)
 313                        break;
 314
 315                switch (rc6_mode(data)) {
 316                case RC6_MODE_0:
 317                        scancode = data->body & 0xffff;
 318                        toggle = data->toggle;
 319                        IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
 320                                   scancode, toggle);
 321                        break;
 322                case RC6_MODE_6A:
 323                        if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
 324                                toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
 325                                scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
 326                        } else {
 327                                toggle = 0;
 328                                scancode = data->body & 0xffffff;
 329                        }
 330
 331                        IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
 332                                   scancode, toggle);
 333                        break;
 334                default:
 335                        IR_dprintk(1, "RC6 unknown mode\n");
 336                        goto out;
 337                }
 338
 339                ir_keydown(input_dev, scancode, toggle);
 340                data->state = STATE_INACTIVE;
 341                return 0;
 342        }
 343
 344out:
 345        IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
 346                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 347        data->state = STATE_INACTIVE;
 348        return -EINVAL;
 349}
 350
 351static int ir_rc6_register(struct input_dev *input_dev)
 352{
 353        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 354        struct decoder_data *data;
 355        int rc;
 356
 357        rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 358        if (rc < 0)
 359                return rc;
 360
 361        data = kzalloc(sizeof(*data), GFP_KERNEL);
 362        if (!data) {
 363                sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 364                return -ENOMEM;
 365        }
 366
 367        data->ir_dev = ir_dev;
 368        data->enabled = 1;
 369
 370        spin_lock(&decoder_lock);
 371        list_add_tail(&data->list, &decoder_list);
 372        spin_unlock(&decoder_lock);
 373
 374        return 0;
 375}
 376
 377static int ir_rc6_unregister(struct input_dev *input_dev)
 378{
 379        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 380        static struct decoder_data *data;
 381
 382        data = get_decoder_data(ir_dev);
 383        if (!data)
 384                return 0;
 385
 386        sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 387
 388        spin_lock(&decoder_lock);
 389        list_del(&data->list);
 390        spin_unlock(&decoder_lock);
 391
 392        return 0;
 393}
 394
 395static struct ir_raw_handler rc6_handler = {
 396        .decode         = ir_rc6_decode,
 397        .raw_register   = ir_rc6_register,
 398        .raw_unregister = ir_rc6_unregister,
 399};
 400
 401static int __init ir_rc6_decode_init(void)
 402{
 403        ir_raw_handler_register(&rc6_handler);
 404
 405        printk(KERN_INFO "IR RC6 protocol handler initialized\n");
 406        return 0;
 407}
 408
 409static void __exit ir_rc6_decode_exit(void)
 410{
 411        ir_raw_handler_unregister(&rc6_handler);
 412}
 413
 414module_init(ir_rc6_decode_init);
 415module_exit(ir_rc6_decode_exit);
 416
 417MODULE_LICENSE("GPL");
 418MODULE_AUTHOR("David H\xC3\xA4rdeman <david@hardeman.nu>");
 419MODULE_DESCRIPTION("RC6 IR protocol decoder");
 420