1 /* ir-rc6-decoder.c - A decoder for the RC6 IR protocol 2 * 3 * Copyright (C) 2010 by David Härdeman <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 "rc-core-priv.h" 16 17 /* 18 * This decoder currently supports: 19 * RC6-0-16 (standard toggle bit in header) 20 * RC6-6A-24 (no toggle bit) 21 * RC6-6A-32 (MCE version with toggle bit in body) 22 */ 23 24 #define RC6_UNIT 444444 /* us */ 25 #define RC6_HEADER_NBITS 4 /* not including toggle bit */ 26 #define RC6_0_NBITS 16 27 #define RC6_6A_SMALL_NBITS 24 28 #define RC6_6A_LARGE_NBITS 32 29 #define RC6_PREFIX_PULSE (6 * RC6_UNIT) 30 #define RC6_PREFIX_SPACE (2 * RC6_UNIT) 31 #define RC6_BIT_START (1 * RC6_UNIT) 32 #define RC6_BIT_END (1 * RC6_UNIT) 33 #define RC6_TOGGLE_START (2 * RC6_UNIT) 34 #define RC6_TOGGLE_END (2 * RC6_UNIT) 35 #define RC6_MODE_MASK 0x07 /* for the header bits */ 36 #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 37 #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 38 39 enum rc6_mode { 40 RC6_MODE_0, 41 RC6_MODE_6A, 42 RC6_MODE_UNKNOWN, 43 }; 44 45 enum rc6_state { 46 STATE_INACTIVE, 47 STATE_PREFIX_SPACE, 48 STATE_HEADER_BIT_START, 49 STATE_HEADER_BIT_END, 50 STATE_TOGGLE_START, 51 STATE_TOGGLE_END, 52 STATE_BODY_BIT_START, 53 STATE_BODY_BIT_END, 54 STATE_FINISHED, 55 }; 56 57 static enum rc6_mode rc6_mode(struct rc6_dec *data) 58 { 59 switch (data->header & RC6_MODE_MASK) { 60 case 0: 61 return RC6_MODE_0; 62 case 6: 63 if (!data->toggle) 64 return RC6_MODE_6A; 65 /* fall through */ 66 default: 67 return RC6_MODE_UNKNOWN; 68 } 69 } 70 71 /** 72 * ir_rc6_decode() - Decode one RC6 pulse or space 73 * @dev: the struct rc_dev descriptor of the device 74 * @ev: the struct ir_raw_event descriptor of the pulse/space 75 * 76 * This function returns -EINVAL if the pulse violates the state machine 77 */ 78 static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) 79 { 80 struct rc6_dec *data = &dev->raw->rc6; 81 u32 scancode; 82 u8 toggle; 83 84 if (!(dev->raw->enabled_protocols & IR_TYPE_RC6)) 85 return 0; 86 87 if (!is_timing_event(ev)) { 88 if (ev.reset) 89 data->state = STATE_INACTIVE; 90 return 0; 91 } 92 93 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 94 goto out; 95 96 again: 97 IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", 98 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 99 100 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 101 return 0; 102 103 switch (data->state) { 104 105 case STATE_INACTIVE: 106 if (!ev.pulse) 107 break; 108 109 /* Note: larger margin on first pulse since each RC6_UNIT 110 is quite short and some hardware takes some time to 111 adjust to the signal */ 112 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) 113 break; 114 115 data->state = STATE_PREFIX_SPACE; 116 data->count = 0; 117 return 0; 118 119 case STATE_PREFIX_SPACE: 120 if (ev.pulse) 121 break; 122 123 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) 124 break; 125 126 data->state = STATE_HEADER_BIT_START; 127 return 0; 128 129 case STATE_HEADER_BIT_START: 130 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) 131 break; 132 133 data->header <<= 1; 134 if (ev.pulse) 135 data->header |= 1; 136 data->count++; 137 data->state = STATE_HEADER_BIT_END; 138 return 0; 139 140 case STATE_HEADER_BIT_END: 141 if (!is_transition(&ev, &dev->raw->prev_ev)) 142 break; 143 144 if (data->count == RC6_HEADER_NBITS) 145 data->state = STATE_TOGGLE_START; 146 else 147 data->state = STATE_HEADER_BIT_START; 148 149 decrease_duration(&ev, RC6_BIT_END); 150 goto again; 151 152 case STATE_TOGGLE_START: 153 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) 154 break; 155 156 data->toggle = ev.pulse; 157 data->state = STATE_TOGGLE_END; 158 return 0; 159 160 case STATE_TOGGLE_END: 161 if (!is_transition(&ev, &dev->raw->prev_ev) || 162 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) 163 break; 164 165 if (!(data->header & RC6_STARTBIT_MASK)) { 166 IR_dprintk(1, "RC6 invalid start bit\n"); 167 break; 168 } 169 170 data->state = STATE_BODY_BIT_START; 171 decrease_duration(&ev, RC6_TOGGLE_END); 172 data->count = 0; 173 174 switch (rc6_mode(data)) { 175 case RC6_MODE_0: 176 data->wanted_bits = RC6_0_NBITS; 177 break; 178 case RC6_MODE_6A: 179 /* This might look weird, but we basically 180 check the value of the first body bit to 181 determine the number of bits in mode 6A */ 182 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || 183 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 184 data->wanted_bits = RC6_6A_LARGE_NBITS; 185 else 186 data->wanted_bits = RC6_6A_SMALL_NBITS; 187 break; 188 default: 189 IR_dprintk(1, "RC6 unknown mode\n"); 190 goto out; 191 } 192 goto again; 193 194 case STATE_BODY_BIT_START: 195 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) 196 break; 197 198 data->body <<= 1; 199 if (ev.pulse) 200 data->body |= 1; 201 data->count++; 202 data->state = STATE_BODY_BIT_END; 203 return 0; 204 205 case STATE_BODY_BIT_END: 206 if (!is_transition(&ev, &dev->raw->prev_ev)) 207 break; 208 209 if (data->count == data->wanted_bits) 210 data->state = STATE_FINISHED; 211 else 212 data->state = STATE_BODY_BIT_START; 213 214 decrease_duration(&ev, RC6_BIT_END); 215 goto again; 216 217 case STATE_FINISHED: 218 if (ev.pulse) 219 break; 220 221 switch (rc6_mode(data)) { 222 case RC6_MODE_0: 223 scancode = data->body & 0xffff; 224 toggle = data->toggle; 225 IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", 226 scancode, toggle); 227 break; 228 case RC6_MODE_6A: 229 if (data->wanted_bits == RC6_6A_LARGE_NBITS) { 230 toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; 231 scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; 232 } else { 233 toggle = 0; 234 scancode = data->body & 0xffffff; 235 } 236 237 IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", 238 scancode, toggle); 239 break; 240 default: 241 IR_dprintk(1, "RC6 unknown mode\n"); 242 goto out; 243 } 244 245 rc_keydown(dev, scancode, toggle); 246 data->state = STATE_INACTIVE; 247 return 0; 248 } 249 250 out: 251 IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", 252 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 253 data->state = STATE_INACTIVE; 254 return -EINVAL; 255 } 256 257 static struct ir_raw_handler rc6_handler = { 258 .protocols = IR_TYPE_RC6, 259 .decode = ir_rc6_decode, 260 }; 261 262 static int __init ir_rc6_decode_init(void) 263 { 264 ir_raw_handler_register(&rc6_handler); 265 266 printk(KERN_INFO "IR RC6 protocol handler initialized\n"); 267 return 0; 268 } 269 270 static void __exit ir_rc6_decode_exit(void) 271 { 272 ir_raw_handler_unregister(&rc6_handler); 273 } 274 275 module_init(ir_rc6_decode_init); 276 module_exit(ir_rc6_decode_exit); 277 278 MODULE_LICENSE("GPL"); 279 MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); 280 MODULE_DESCRIPTION("RC6 IR protocol decoder"); 281