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