linux/drivers/media/rc/img-ir/img-ir-nec.c
<<
>>
Prefs
   1/*
   2 * ImgTec IR Decoder setup for NEC protocol.
   3 *
   4 * Copyright 2010-2014 Imagination Technologies Ltd.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by the
   8 * Free Software Foundation; either version 2 of the License, or (at your
   9 * option) any later version.
  10 */
  11
  12#include "img-ir-hw.h"
  13#include <linux/bitrev.h>
  14
  15/* Convert NEC data to a scancode */
  16static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,
  17                               struct img_ir_scancode_req *request)
  18{
  19        unsigned int addr, addr_inv, data, data_inv;
  20        /* a repeat code has no data */
  21        if (!len)
  22                return IMG_IR_REPEATCODE;
  23        if (len != 32)
  24                return -EINVAL;
  25        /* raw encoding: ddDDaaAA */
  26        addr     = (raw >>  0) & 0xff;
  27        addr_inv = (raw >>  8) & 0xff;
  28        data     = (raw >> 16) & 0xff;
  29        data_inv = (raw >> 24) & 0xff;
  30        if ((data_inv ^ data) != 0xff) {
  31                /* 32-bit NEC (used by Apple and TiVo remotes) */
  32                /* scan encoding: as transmitted, MSBit = first received bit */
  33                request->scancode = bitrev8(addr)     << 24 |
  34                                bitrev8(addr_inv) << 16 |
  35                                bitrev8(data)     <<  8 |
  36                                bitrev8(data_inv);
  37                request->protocol = RC_TYPE_NEC32;
  38        } else if ((addr_inv ^ addr) != 0xff) {
  39                /* Extended NEC */
  40                /* scan encoding: AAaaDD */
  41                request->scancode = addr     << 16 |
  42                                addr_inv <<  8 |
  43                                data;
  44                request->protocol = RC_TYPE_NECX;
  45        } else {
  46                /* Normal NEC */
  47                /* scan encoding: AADD */
  48                request->scancode = addr << 8 |
  49                                data;
  50                request->protocol = RC_TYPE_NEC;
  51        }
  52        return IMG_IR_SCANCODE;
  53}
  54
  55/* Convert NEC scancode to NEC data filter */
  56static int img_ir_nec_filter(const struct rc_scancode_filter *in,
  57                             struct img_ir_filter *out, u64 protocols)
  58{
  59        unsigned int addr, addr_inv, data, data_inv;
  60        unsigned int addr_m, addr_inv_m, data_m, data_inv_m;
  61
  62        data       = in->data & 0xff;
  63        data_m     = in->mask & 0xff;
  64
  65        if ((in->data | in->mask) & 0xff000000) {
  66                /* 32-bit NEC (used by Apple and TiVo remotes) */
  67                /* scan encoding: as transmitted, MSBit = first received bit */
  68                addr       = bitrev8(in->data >> 24);
  69                addr_m     = bitrev8(in->mask >> 24);
  70                addr_inv   = bitrev8(in->data >> 16);
  71                addr_inv_m = bitrev8(in->mask >> 16);
  72                data       = bitrev8(in->data >>  8);
  73                data_m     = bitrev8(in->mask >>  8);
  74                data_inv   = bitrev8(in->data >>  0);
  75                data_inv_m = bitrev8(in->mask >>  0);
  76        } else if ((in->data | in->mask) & 0x00ff0000) {
  77                /* Extended NEC */
  78                /* scan encoding AAaaDD */
  79                addr       = (in->data >> 16) & 0xff;
  80                addr_m     = (in->mask >> 16) & 0xff;
  81                addr_inv   = (in->data >>  8) & 0xff;
  82                addr_inv_m = (in->mask >>  8) & 0xff;
  83                data_inv   = data ^ 0xff;
  84                data_inv_m = data_m;
  85        } else {
  86                /* Normal NEC */
  87                /* scan encoding: AADD */
  88                addr       = (in->data >>  8) & 0xff;
  89                addr_m     = (in->mask >>  8) & 0xff;
  90                addr_inv   = addr ^ 0xff;
  91                addr_inv_m = addr_m;
  92                data_inv   = data ^ 0xff;
  93                data_inv_m = data_m;
  94        }
  95
  96        /* raw encoding: ddDDaaAA */
  97        out->data = data_inv << 24 |
  98                    data     << 16 |
  99                    addr_inv <<  8 |
 100                    addr;
 101        out->mask = data_inv_m << 24 |
 102                    data_m     << 16 |
 103                    addr_inv_m <<  8 |
 104                    addr_m;
 105        return 0;
 106}
 107
 108/*
 109 * NEC decoder
 110 * See also http://www.sbprojects.com/knowledge/ir/nec.php
 111 *        http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol
 112 */
 113struct img_ir_decoder img_ir_nec = {
 114        .type = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32,
 115        .control = {
 116                .decoden = 1,
 117                .code_type = IMG_IR_CODETYPE_PULSEDIST,
 118        },
 119        /* main timings */
 120        .unit = 562500, /* 562.5 us */
 121        .timings = {
 122                /* leader symbol */
 123                .ldr = {
 124                        .pulse = { 16   /* 9ms */ },
 125                        .space = { 8    /* 4.5ms */ },
 126                },
 127                /* 0 symbol */
 128                .s00 = {
 129                        .pulse = { 1    /* 562.5 us */ },
 130                        .space = { 1    /* 562.5 us */ },
 131                },
 132                /* 1 symbol */
 133                .s01 = {
 134                        .pulse = { 1    /* 562.5 us */ },
 135                        .space = { 3    /* 1687.5 us */ },
 136                },
 137                /* free time */
 138                .ft = {
 139                        .minlen = 32,
 140                        .maxlen = 32,
 141                        .ft_min = 10,   /* 5.625 ms */
 142                },
 143        },
 144        /* repeat codes */
 145        .repeat = 108,                  /* 108 ms */
 146        .rtimings = {
 147                /* leader symbol */
 148                .ldr = {
 149                        .space = { 4    /* 2.25 ms */ },
 150                },
 151                /* free time */
 152                .ft = {
 153                        .minlen = 0,    /* repeat code has no data */
 154                        .maxlen = 0,
 155                },
 156        },
 157        /* scancode logic */
 158        .scancode = img_ir_nec_scancode,
 159        .filter = img_ir_nec_filter,
 160};
 161