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 */ 16 static 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 */ 56 static 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 */ 113 struct 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