linux/drivers/media/IR/ir-functions.c
<<
>>
Prefs
   1/*
   2 *
   3 * some common structs and functions to handle infrared remotes via
   4 * input layer ...
   5 *
   6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License as published by
  10 *  the Free Software Foundation; either version 2 of the License, or
  11 *  (at your option) any later version.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *  GNU General Public License for more details.
  17 *
  18 *  You should have received a copy of the GNU General Public License
  19 *  along with this program; if not, write to the Free Software
  20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/string.h>
  25#include <linux/jiffies.h>
  26#include <media/ir-common.h>
  27#include "ir-core-priv.h"
  28
  29/* -------------------------------------------------------------------------- */
  30
  31MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  32MODULE_LICENSE("GPL");
  33
  34static int repeat = 1;
  35module_param(repeat, int, 0444);
  36MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
  37
  38/* -------------------------------------------------------------------------- */
  39
  40static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
  41{
  42        if (KEY_RESERVED == ir->keycode) {
  43                printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n",
  44                       dev->name, ir->ir_key, ir->keypressed);
  45                return;
  46        }
  47        IR_dprintk(1,"%s: key event code=%d down=%d\n",
  48                dev->name,ir->keycode,ir->keypressed);
  49        input_report_key(dev,ir->keycode,ir->keypressed);
  50        input_sync(dev);
  51}
  52
  53/* -------------------------------------------------------------------------- */
  54
  55int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
  56                  const u64 ir_type)
  57{
  58        ir->ir_type = ir_type;
  59
  60        if (repeat)
  61                set_bit(EV_REP, dev->evbit);
  62
  63        return 0;
  64}
  65EXPORT_SYMBOL_GPL(ir_input_init);
  66
  67
  68void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
  69{
  70        if (ir->keypressed) {
  71                ir->keypressed = 0;
  72                ir_input_key_event(dev,ir);
  73        }
  74}
  75EXPORT_SYMBOL_GPL(ir_input_nokey);
  76
  77void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
  78                      u32 ir_key)
  79{
  80        u32 keycode = ir_g_keycode_from_table(dev, ir_key);
  81
  82        if (ir->keypressed && ir->keycode != keycode) {
  83                ir->keypressed = 0;
  84                ir_input_key_event(dev,ir);
  85        }
  86        if (!ir->keypressed) {
  87                ir->ir_key  = ir_key;
  88                ir->keycode = keycode;
  89                ir->keypressed = 1;
  90                ir_input_key_event(dev,ir);
  91        }
  92}
  93EXPORT_SYMBOL_GPL(ir_input_keydown);
  94
  95/* -------------------------------------------------------------------------- */
  96/* extract mask bits out of data and pack them into the result */
  97u32 ir_extract_bits(u32 data, u32 mask)
  98{
  99        u32 vbit = 1, value = 0;
 100
 101        do {
 102            if (mask&1) {
 103                if (data&1)
 104                        value |= vbit;
 105                vbit<<=1;
 106            }
 107            data>>=1;
 108        } while (mask>>=1);
 109
 110        return value;
 111}
 112EXPORT_SYMBOL_GPL(ir_extract_bits);
 113
 114static int inline getbit(u32 *samples, int bit)
 115{
 116        return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0;
 117}
 118
 119/* sump raw samples for visual debugging ;) */
 120int ir_dump_samples(u32 *samples, int count)
 121{
 122        int i, bit, start;
 123
 124        printk(KERN_DEBUG "ir samples: ");
 125        start = 0;
 126        for (i = 0; i < count * 32; i++) {
 127                bit = getbit(samples,i);
 128                if (bit)
 129                        start = 1;
 130                if (0 == start)
 131                        continue;
 132                printk("%s", bit ? "#" : "_");
 133        }
 134        printk("\n");
 135        return 0;
 136}
 137EXPORT_SYMBOL_GPL(ir_dump_samples);
 138
 139/* decode raw samples, pulse distance coding used by NEC remotes */
 140int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
 141{
 142        int i,last,bit,len;
 143        u32 curBit;
 144        u32 value;
 145
 146        /* find start burst */
 147        for (i = len = 0; i < count * 32; i++) {
 148                bit = getbit(samples,i);
 149                if (bit) {
 150                        len++;
 151                } else {
 152                        if (len >= 29)
 153                                break;
 154                        len = 0;
 155                }
 156        }
 157
 158        /* start burst to short */
 159        if (len < 29)
 160                return 0xffffffff;
 161
 162        /* find start silence */
 163        for (len = 0; i < count * 32; i++) {
 164                bit = getbit(samples,i);
 165                if (bit) {
 166                        break;
 167                } else {
 168                        len++;
 169                }
 170        }
 171
 172        /* silence to short */
 173        if (len < 7)
 174                return 0xffffffff;
 175
 176        /* go decoding */
 177        len   = 0;
 178        last = 1;
 179        value = 0; curBit = 1;
 180        for (; i < count * 32; i++) {
 181                bit  = getbit(samples,i);
 182                if (last) {
 183                        if(bit) {
 184                                continue;
 185                        } else {
 186                                len = 1;
 187                        }
 188                } else {
 189                        if (bit) {
 190                                if (len > (low + high) /2)
 191                                        value |= curBit;
 192                                curBit <<= 1;
 193                                if (curBit == 1)
 194                                        break;
 195                        } else {
 196                                len++;
 197                        }
 198                }
 199                last = bit;
 200        }
 201
 202        return value;
 203}
 204EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
 205
 206/* decode raw samples, biphase coding, used by rc5 for example */
 207int ir_decode_biphase(u32 *samples, int count, int low, int high)
 208{
 209        int i,last,bit,len,flips;
 210        u32 value;
 211
 212        /* find start bit (1) */
 213        for (i = 0; i < 32; i++) {
 214                bit = getbit(samples,i);
 215                if (bit)
 216                        break;
 217        }
 218
 219        /* go decoding */
 220        len   = 0;
 221        flips = 0;
 222        value = 1;
 223        for (; i < count * 32; i++) {
 224                if (len > high)
 225                        break;
 226                if (flips > 1)
 227                        break;
 228                last = bit;
 229                bit  = getbit(samples,i);
 230                if (last == bit) {
 231                        len++;
 232                        continue;
 233                }
 234                if (len < low) {
 235                        len++;
 236                        flips++;
 237                        continue;
 238                }
 239                value <<= 1;
 240                value |= bit;
 241                flips = 0;
 242                len   = 1;
 243        }
 244        return value;
 245}
 246EXPORT_SYMBOL_GPL(ir_decode_biphase);
 247
 248/* RC5 decoding stuff, moved from bttv-input.c to share it with
 249 * saa7134 */
 250
 251/* decode raw bit pattern to RC5 code */
 252u32 ir_rc5_decode(unsigned int code)
 253{
 254        unsigned int org_code = code;
 255        unsigned int pair;
 256        unsigned int rc5 = 0;
 257        int i;
 258
 259        for (i = 0; i < 14; ++i) {
 260                pair = code & 0x3;
 261                code >>= 2;
 262
 263                rc5 <<= 1;
 264                switch (pair) {
 265                case 0:
 266                case 2:
 267                        break;
 268                case 1:
 269                        rc5 |= 1;
 270                        break;
 271                case 3:
 272                        IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);
 273                        return 0;
 274                }
 275        }
 276        IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
 277                "instr=%x\n", rc5, org_code, RC5_START(rc5),
 278                RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
 279        return rc5;
 280}
 281EXPORT_SYMBOL_GPL(ir_rc5_decode);
 282
 283void ir_rc5_timer_end(unsigned long data)
 284{
 285        struct card_ir *ir = (struct card_ir *)data;
 286        struct timeval tv;
 287        unsigned long current_jiffies, timeout;
 288        u32 gap;
 289        u32 rc5 = 0;
 290
 291        /* get time */
 292        current_jiffies = jiffies;
 293        do_gettimeofday(&tv);
 294
 295        /* avoid overflow with gap >1s */
 296        if (tv.tv_sec - ir->base_time.tv_sec > 1) {
 297                gap = 200000;
 298        } else {
 299                gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
 300                    tv.tv_usec - ir->base_time.tv_usec;
 301        }
 302
 303        /* signal we're ready to start a new code */
 304        ir->active = 0;
 305
 306        /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
 307        if (gap < 28000) {
 308                IR_dprintk(1, "ir-common: spurious timer_end\n");
 309                return;
 310        }
 311
 312        if (ir->last_bit < 20) {
 313                /* ignore spurious codes (caused by light/other remotes) */
 314                IR_dprintk(1, "ir-common: short code: %x\n", ir->code);
 315        } else {
 316                ir->code = (ir->code << ir->shift_by) | 1;
 317                rc5 = ir_rc5_decode(ir->code);
 318
 319                /* two start bits? */
 320                if (RC5_START(rc5) != ir->start) {
 321                        IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5));
 322
 323                        /* right address? */
 324                } else if (RC5_ADDR(rc5) == ir->addr) {
 325                        u32 toggle = RC5_TOGGLE(rc5);
 326                        u32 instr = RC5_INSTR(rc5);
 327
 328                        /* Good code, decide if repeat/repress */
 329                        if (toggle != RC5_TOGGLE(ir->last_rc5) ||
 330                            instr != RC5_INSTR(ir->last_rc5)) {
 331                                IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr,
 332                                        toggle);
 333                                ir_input_nokey(ir->dev, &ir->ir);
 334                                ir_input_keydown(ir->dev, &ir->ir, instr);
 335                        }
 336
 337                        /* Set/reset key-up timer */
 338                        timeout = current_jiffies +
 339                                  msecs_to_jiffies(ir->rc5_key_timeout);
 340                        mod_timer(&ir->timer_keyup, timeout);
 341
 342                        /* Save code for repeat test */
 343                        ir->last_rc5 = rc5;
 344                }
 345        }
 346}
 347EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
 348
 349void ir_rc5_timer_keyup(unsigned long data)
 350{
 351        struct card_ir *ir = (struct card_ir *)data;
 352
 353        IR_dprintk(1, "ir-common: key released\n");
 354        ir_input_nokey(ir->dev, &ir->ir);
 355}
 356EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
 357