aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc/ir-rc6-decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/rc/ir-rc6-decoder.c')
-rw-r--r--drivers/media/rc/ir-rc6-decoder.c67
1 files changed, 41 insertions, 26 deletions
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index 140fb67e2f89..4cfdd7fa4bbd 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -18,24 +18,31 @@
18/* 18/*
19 * This decoder currently supports: 19 * This decoder currently supports:
20 * RC6-0-16 (standard toggle bit in header) 20 * RC6-0-16 (standard toggle bit in header)
21 * RC6-6A-20 (no toggle bit)
21 * RC6-6A-24 (no toggle bit) 22 * RC6-6A-24 (no toggle bit)
22 * RC6-6A-32 (MCE version with toggle bit in body) 23 * RC6-6A-32 (MCE version with toggle bit in body)
23 */ 24 */
24 25
25#define RC6_UNIT 444444 /* us */ 26#define RC6_UNIT 444444 /* nanosecs */
26#define RC6_HEADER_NBITS 4 /* not including toggle bit */ 27#define RC6_HEADER_NBITS 4 /* not including toggle bit */
27#define RC6_0_NBITS 16 28#define RC6_0_NBITS 16
28#define RC6_6A_SMALL_NBITS 24 29#define RC6_6A_32_NBITS 32
29#define RC6_6A_LARGE_NBITS 32 30#define RC6_6A_NBITS 128 /* Variable 8..128 */
30#define RC6_PREFIX_PULSE (6 * RC6_UNIT) 31#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
31#define RC6_PREFIX_SPACE (2 * RC6_UNIT) 32#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
32#define RC6_BIT_START (1 * RC6_UNIT) 33#define RC6_BIT_START (1 * RC6_UNIT)
33#define RC6_BIT_END (1 * RC6_UNIT) 34#define RC6_BIT_END (1 * RC6_UNIT)
34#define RC6_TOGGLE_START (2 * RC6_UNIT) 35#define RC6_TOGGLE_START (2 * RC6_UNIT)
35#define RC6_TOGGLE_END (2 * RC6_UNIT) 36#define RC6_TOGGLE_END (2 * RC6_UNIT)
37#define RC6_SUFFIX_SPACE (6 * RC6_UNIT)
36#define RC6_MODE_MASK 0x07 /* for the header bits */ 38#define RC6_MODE_MASK 0x07 /* for the header bits */
37#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 39#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
38#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 40#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
41#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */
42#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */
43#ifndef CHAR_BIT
44#define CHAR_BIT 8 /* Normally in <limits.h> */
45#endif
39 46
40enum rc6_mode { 47enum rc6_mode {
41 RC6_MODE_0, 48 RC6_MODE_0,
@@ -125,6 +132,7 @@ again:
125 break; 132 break;
126 133
127 data->state = STATE_HEADER_BIT_START; 134 data->state = STATE_HEADER_BIT_START;
135 data->header = 0;
128 return 0; 136 return 0;
129 137
130 case STATE_HEADER_BIT_START: 138 case STATE_HEADER_BIT_START:
@@ -171,20 +179,14 @@ again:
171 data->state = STATE_BODY_BIT_START; 179 data->state = STATE_BODY_BIT_START;
172 decrease_duration(&ev, RC6_TOGGLE_END); 180 decrease_duration(&ev, RC6_TOGGLE_END);
173 data->count = 0; 181 data->count = 0;
182 data->body = 0;
174 183
175 switch (rc6_mode(data)) { 184 switch (rc6_mode(data)) {
176 case RC6_MODE_0: 185 case RC6_MODE_0:
177 data->wanted_bits = RC6_0_NBITS; 186 data->wanted_bits = RC6_0_NBITS;
178 break; 187 break;
179 case RC6_MODE_6A: 188 case RC6_MODE_6A:
180 /* This might look weird, but we basically 189 data->wanted_bits = RC6_6A_NBITS;
181 check the value of the first body bit to
182 determine the number of bits in mode 6A */
183 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
184 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
185 data->wanted_bits = RC6_6A_LARGE_NBITS;
186 else
187 data->wanted_bits = RC6_6A_SMALL_NBITS;
188 break; 190 break;
189 default: 191 default:
190 IR_dprintk(1, "RC6 unknown mode\n"); 192 IR_dprintk(1, "RC6 unknown mode\n");
@@ -193,15 +195,21 @@ again:
193 goto again; 195 goto again;
194 196
195 case STATE_BODY_BIT_START: 197 case STATE_BODY_BIT_START:
196 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) 198 if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
197 break; 199 /* Discard LSB's that won't fit in data->body */
198 200 if (data->count++ < CHAR_BIT * sizeof data->body) {
199 data->body <<= 1; 201 data->body <<= 1;
200 if (ev.pulse) 202 if (ev.pulse)
201 data->body |= 1; 203 data->body |= 1;
202 data->count++; 204 }
203 data->state = STATE_BODY_BIT_END; 205 data->state = STATE_BODY_BIT_END;
204 return 0; 206 return 0;
207 } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
208 geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
209 data->state = STATE_FINISHED;
210 goto again;
211 }
212 break;
205 213
206 case STATE_BODY_BIT_END: 214 case STATE_BODY_BIT_END:
207 if (!is_transition(&ev, &dev->raw->prev_ev)) 215 if (!is_transition(&ev, &dev->raw->prev_ev))
@@ -221,20 +229,27 @@ again:
221 229
222 switch (rc6_mode(data)) { 230 switch (rc6_mode(data)) {
223 case RC6_MODE_0: 231 case RC6_MODE_0:
224 scancode = data->body & 0xffff; 232 scancode = data->body;
225 toggle = data->toggle; 233 toggle = data->toggle;
226 IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", 234 IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
227 scancode, toggle); 235 scancode, toggle);
228 break; 236 break;
229 case RC6_MODE_6A: 237 case RC6_MODE_6A:
230 if (data->wanted_bits == RC6_6A_LARGE_NBITS) { 238 if (data->count > CHAR_BIT * sizeof data->body) {
231 toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; 239 IR_dprintk(1, "RC6 too many (%u) data bits\n",
232 scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; 240 data->count);
241 goto out;
242 }
243
244 scancode = data->body;
245 if (data->count == RC6_6A_32_NBITS &&
246 (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
247 /* MCE RC */
248 toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
249 scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
233 } else { 250 } else {
234 toggle = 0; 251 toggle = 0;
235 scancode = data->body & 0xffffff;
236 } 252 }
237
238 IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", 253 IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
239 scancode, toggle); 254 scancode, toggle);
240 break; 255 break;