linux/drivers/media/IR/ir-jvc-decoder.c
<<
>>
Prefs
   1/* ir-jvc-decoder.c - handle JVC IR Pulse/Space 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 <linux/bitrev.h>
  16#include "ir-core-priv.h"
  17
  18#define JVC_NBITS               16              /* dev(8) + func(8) */
  19#define JVC_UNIT                525000          /* ns */
  20#define JVC_HEADER_PULSE        (16 * JVC_UNIT) /* lack of header -> repeat */
  21#define JVC_HEADER_SPACE        (8  * JVC_UNIT)
  22#define JVC_BIT_PULSE           (1  * JVC_UNIT)
  23#define JVC_BIT_0_SPACE         (1  * JVC_UNIT)
  24#define JVC_BIT_1_SPACE         (3  * JVC_UNIT)
  25#define JVC_TRAILER_PULSE       (1  * JVC_UNIT)
  26#define JVC_TRAILER_SPACE       (35 * JVC_UNIT)
  27
  28/* Used to register jvc_decoder clients */
  29static LIST_HEAD(decoder_list);
  30DEFINE_SPINLOCK(decoder_lock);
  31
  32enum jvc_state {
  33        STATE_INACTIVE,
  34        STATE_HEADER_SPACE,
  35        STATE_BIT_PULSE,
  36        STATE_BIT_SPACE,
  37        STATE_TRAILER_PULSE,
  38        STATE_TRAILER_SPACE,
  39};
  40
  41struct decoder_data {
  42        struct list_head        list;
  43        struct ir_input_dev     *ir_dev;
  44        int                     enabled:1;
  45
  46        /* State machine control */
  47        enum jvc_state          state;
  48        u16                     jvc_bits;
  49        u16                     jvc_old_bits;
  50        unsigned                count;
  51        bool                    first;
  52        bool                    toggle;
  53};
  54
  55
  56/**
  57 * get_decoder_data()   - gets decoder data
  58 * @input_dev:  input device
  59 *
  60 * Returns the struct decoder_data that corresponds to a device
  61 */
  62static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
  63{
  64        struct decoder_data *data = NULL;
  65
  66        spin_lock(&decoder_lock);
  67        list_for_each_entry(data, &decoder_list, list) {
  68                if (data->ir_dev == ir_dev)
  69                        break;
  70        }
  71        spin_unlock(&decoder_lock);
  72        return data;
  73}
  74
  75static ssize_t store_enabled(struct device *d,
  76                             struct device_attribute *mattr,
  77                             const char *buf,
  78                             size_t len)
  79{
  80        unsigned long value;
  81        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  82        struct decoder_data *data = get_decoder_data(ir_dev);
  83
  84        if (!data)
  85                return -EINVAL;
  86
  87        if (strict_strtoul(buf, 10, &value) || value > 1)
  88                return -EINVAL;
  89
  90        data->enabled = value;
  91
  92        return len;
  93}
  94
  95static ssize_t show_enabled(struct device *d,
  96                             struct device_attribute *mattr, char *buf)
  97{
  98        struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  99        struct decoder_data *data = get_decoder_data(ir_dev);
 100
 101        if (!data)
 102                return -EINVAL;
 103
 104        if (data->enabled)
 105                return sprintf(buf, "1\n");
 106        else
 107        return sprintf(buf, "0\n");
 108}
 109
 110static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
 111
 112static struct attribute *decoder_attributes[] = {
 113        &dev_attr_enabled.attr,
 114        NULL
 115};
 116
 117static struct attribute_group decoder_attribute_group = {
 118        .name   = "jvc_decoder",
 119        .attrs  = decoder_attributes,
 120};
 121
 122/**
 123 * ir_jvc_decode() - Decode one JVC pulse or space
 124 * @input_dev:  the struct input_dev descriptor of the device
 125 * @duration:   the struct ir_raw_event descriptor of the pulse/space
 126 *
 127 * This function returns -EINVAL if the pulse violates the state machine
 128 */
 129static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 130{
 131        struct decoder_data *data;
 132        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 133
 134        data = get_decoder_data(ir_dev);
 135        if (!data)
 136                return -EINVAL;
 137
 138        if (!data->enabled)
 139                return 0;
 140
 141        if (IS_RESET(ev)) {
 142                data->state = STATE_INACTIVE;
 143                return 0;
 144        }
 145
 146        if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
 147                goto out;
 148
 149        IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
 150                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 151
 152        switch (data->state) {
 153
 154        case STATE_INACTIVE:
 155                if (!ev.pulse)
 156                        break;
 157
 158                if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
 159                        break;
 160
 161                data->count = 0;
 162                data->first = true;
 163                data->toggle = !data->toggle;
 164                data->state = STATE_HEADER_SPACE;
 165                return 0;
 166
 167        case STATE_HEADER_SPACE:
 168                if (ev.pulse)
 169                        break;
 170
 171                if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
 172                        break;
 173
 174                data->state = STATE_BIT_PULSE;
 175                return 0;
 176
 177        case STATE_BIT_PULSE:
 178                if (!ev.pulse)
 179                        break;
 180
 181                if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
 182                        break;
 183
 184                data->state = STATE_BIT_SPACE;
 185                return 0;
 186
 187        case STATE_BIT_SPACE:
 188                if (ev.pulse)
 189                        break;
 190
 191                data->jvc_bits <<= 1;
 192                if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
 193                        data->jvc_bits |= 1;
 194                        decrease_duration(&ev, JVC_BIT_1_SPACE);
 195                } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
 196                        decrease_duration(&ev, JVC_BIT_0_SPACE);
 197                else
 198                        break;
 199                data->count++;
 200
 201                if (data->count == JVC_NBITS)
 202                        data->state = STATE_TRAILER_PULSE;
 203                else
 204                        data->state = STATE_BIT_PULSE;
 205                return 0;
 206
 207        case STATE_TRAILER_PULSE:
 208                if (!ev.pulse)
 209                        break;
 210
 211                if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
 212                        break;
 213
 214                data->state = STATE_TRAILER_SPACE;
 215                return 0;
 216
 217        case STATE_TRAILER_SPACE:
 218                if (ev.pulse)
 219                        break;
 220
 221                if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
 222                        break;
 223
 224                if (data->first) {
 225                        u32 scancode;
 226                        scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
 227                                   (bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
 228                        IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
 229                        ir_keydown(input_dev, scancode, data->toggle);
 230                        data->first = false;
 231                        data->jvc_old_bits = data->jvc_bits;
 232                } else if (data->jvc_bits == data->jvc_old_bits) {
 233                        IR_dprintk(1, "JVC repeat\n");
 234                        ir_repeat(input_dev);
 235                } else {
 236                        IR_dprintk(1, "JVC invalid repeat msg\n");
 237                        break;
 238                }
 239
 240                data->count = 0;
 241                data->state = STATE_BIT_PULSE;
 242                return 0;
 243        }
 244
 245out:
 246        IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
 247                   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 248        data->state = STATE_INACTIVE;
 249        return -EINVAL;
 250}
 251
 252static int ir_jvc_register(struct input_dev *input_dev)
 253{
 254        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 255        struct decoder_data *data;
 256        int rc;
 257
 258        rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 259        if (rc < 0)
 260                return rc;
 261
 262        data = kzalloc(sizeof(*data), GFP_KERNEL);
 263        if (!data) {
 264                sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 265                return -ENOMEM;
 266        }
 267
 268        data->ir_dev = ir_dev;
 269        data->enabled = 1;
 270
 271        spin_lock(&decoder_lock);
 272        list_add_tail(&data->list, &decoder_list);
 273        spin_unlock(&decoder_lock);
 274
 275        return 0;
 276}
 277
 278static int ir_jvc_unregister(struct input_dev *input_dev)
 279{
 280        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 281        static struct decoder_data *data;
 282
 283        data = get_decoder_data(ir_dev);
 284        if (!data)
 285                return 0;
 286
 287        sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
 288
 289        spin_lock(&decoder_lock);
 290        list_del(&data->list);
 291        spin_unlock(&decoder_lock);
 292
 293        return 0;
 294}
 295
 296static struct ir_raw_handler jvc_handler = {
 297        .decode         = ir_jvc_decode,
 298        .raw_register   = ir_jvc_register,
 299        .raw_unregister = ir_jvc_unregister,
 300};
 301
 302static int __init ir_jvc_decode_init(void)
 303{
 304        ir_raw_handler_register(&jvc_handler);
 305
 306        printk(KERN_INFO "IR JVC protocol handler initialized\n");
 307        return 0;
 308}
 309
 310static void __exit ir_jvc_decode_exit(void)
 311{
 312        ir_raw_handler_unregister(&jvc_handler);
 313}
 314
 315module_init(ir_jvc_decode_init);
 316module_exit(ir_jvc_decode_exit);
 317
 318MODULE_LICENSE("GPL");
 319MODULE_AUTHOR("David H\xC3\xA4rdeman <david@hardeman.nu>");
 320MODULE_DESCRIPTION("JVC IR protocol decoder");
 321