diff options
Diffstat (limited to 'drivers/media/rc/ir-rc6-decoder.c')
-rw-r--r-- | drivers/media/rc/ir-rc6-decoder.c | 67 |
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 | ||
40 | enum rc6_mode { | 47 | enum 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; |