aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-rc6-decoder.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-04-15 17:46:00 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:57:42 -0400
commite40b1127f994a427568319d1be9b9e5ab1f58dd1 (patch)
tree5d4f892dbe90588f8932cd4e1768b953814f3f47 /drivers/media/IR/ir-rc6-decoder.c
parent21677cfc562a27e099719d413287bc8d1d24deb7 (diff)
V4L/DVB: ir-core: change duration to be coded as a u32 integer
This patch implements the agreed upon 1:31 integer encoded pulse/duration struct for ir-core raw decoders. All decoders have been tested after the change. Comments are welcome. Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/IR/ir-rc6-decoder.c')
-rw-r--r--drivers/media/IR/ir-rc6-decoder.c221
1 files changed, 114 insertions, 107 deletions
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index ccc5be240f82..2bf479f4f1bc 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -26,8 +26,12 @@
26#define RC6_0_NBITS 16 26#define RC6_0_NBITS 16
27#define RC6_6A_SMALL_NBITS 24 27#define RC6_6A_SMALL_NBITS 24
28#define RC6_6A_LARGE_NBITS 32 28#define RC6_6A_LARGE_NBITS 32
29#define RC6_PREFIX_PULSE PULSE(6) 29#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
30#define RC6_PREFIX_SPACE SPACE(2) 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)
31#define RC6_MODE_MASK 0x07 /* for the header bits */ 35#define RC6_MODE_MASK 0x07 /* for the header bits */
32#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
33#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
@@ -63,7 +67,7 @@ struct decoder_data {
63 enum rc6_state state; 67 enum rc6_state state;
64 u8 header; 68 u8 header;
65 u32 body; 69 u32 body;
66 int last_unit; 70 struct ir_raw_event prev_ev;
67 bool toggle; 71 bool toggle;
68 unsigned count; 72 unsigned count;
69 unsigned wanted_bits; 73 unsigned wanted_bits;
@@ -152,17 +156,16 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
152/** 156/**
153 * ir_rc6_decode() - Decode one RC6 pulse or space 157 * ir_rc6_decode() - Decode one RC6 pulse or space
154 * @input_dev: the struct input_dev descriptor of the device 158 * @input_dev: the struct input_dev descriptor of the device
155 * @duration: duration of pulse/space in ns 159 * @ev: the struct ir_raw_event descriptor of the pulse/space
156 * 160 *
157 * This function returns -EINVAL if the pulse violates the state machine 161 * This function returns -EINVAL if the pulse violates the state machine
158 */ 162 */
159static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) 163static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
160{ 164{
161 struct decoder_data *data; 165 struct decoder_data *data;
162 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 166 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
163 u32 scancode; 167 u32 scancode;
164 u8 toggle; 168 u8 toggle;
165 int u;
166 169
167 data = get_decoder_data(ir_dev); 170 data = get_decoder_data(ir_dev);
168 if (!data) 171 if (!data)
@@ -171,140 +174,144 @@ static int ir_rc6_decode(struct input_dev *input_dev, s64 duration)
171 if (!data->enabled) 174 if (!data->enabled)
172 return 0; 175 return 0;
173 176
174 if (IS_RESET(duration)) { 177 if (IS_RESET(ev)) {
175 data->state = STATE_INACTIVE; 178 data->state = STATE_INACTIVE;
176 return 0; 179 return 0;
177 } 180 }
178 181
179 u = TO_UNITS(duration, RC6_UNIT); 182 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
180 if (DURATION(u) == 0)
181 goto out; 183 goto out;
182 184
183again: 185again:
184 IR_dprintk(2, "RC6 decode started at state %i (%i units, %ius)\n", 186 IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
185 data->state, u, TO_US(duration)); 187 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
186 188
187 if (DURATION(u) == 0 && data->state != STATE_FINISHED) 189 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
188 return 0; 190 return 0;
189 191
190 switch (data->state) { 192 switch (data->state) {
191 193
192 case STATE_INACTIVE: 194 case STATE_INACTIVE:
193 if (u >= RC6_PREFIX_PULSE - 1 && u <= RC6_PREFIX_PULSE + 1) { 195 if (!ev.pulse)
194 data->state = STATE_PREFIX_SPACE; 196 break;
195 data->count = 0; 197
196 return 0; 198 /* Note: larger margin on first pulse since each RC6_UNIT
197 } 199 is quite short and some hardware takes some time to
198 break; 200 adjust to the signal */
201 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
202 break;
203
204 data->state = STATE_PREFIX_SPACE;
205 data->count = 0;
206 return 0;
199 207
200 case STATE_PREFIX_SPACE: 208 case STATE_PREFIX_SPACE:
201 if (u == RC6_PREFIX_SPACE) { 209 if (ev.pulse)
202 data->state = STATE_HEADER_BIT_START; 210 break;
203 return 0; 211
204 } 212 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
205 break; 213 break;
214
215 data->state = STATE_HEADER_BIT_START;
216 return 0;
206 217
207 case STATE_HEADER_BIT_START: 218 case STATE_HEADER_BIT_START:
208 if (DURATION(u) == 1) { 219 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
209 data->header <<= 1; 220 break;
210 if (IS_PULSE(u)) 221
211 data->header |= 1; 222 data->header <<= 1;
212 data->count++; 223 if (ev.pulse)
213 data->last_unit = u; 224 data->header |= 1;
214 data->state = STATE_HEADER_BIT_END; 225 data->count++;
215 return 0; 226 data->prev_ev = ev;
216 } 227 data->state = STATE_HEADER_BIT_END;
217 break; 228 return 0;
218 229
219 case STATE_HEADER_BIT_END: 230 case STATE_HEADER_BIT_END:
220 if (IS_TRANSITION(u, data->last_unit)) { 231 if (!is_transition(&ev, &data->prev_ev))
221 if (data->count == RC6_HEADER_NBITS) 232 break;
222 data->state = STATE_TOGGLE_START;
223 else
224 data->state = STATE_HEADER_BIT_START;
225 233
226 DECREASE_DURATION(u, 1); 234 if (data->count == RC6_HEADER_NBITS)
227 goto again; 235 data->state = STATE_TOGGLE_START;
228 } 236 else
229 break; 237 data->state = STATE_HEADER_BIT_START;
238
239 decrease_duration(&ev, RC6_BIT_END);
240 goto again;
230 241
231 case STATE_TOGGLE_START: 242 case STATE_TOGGLE_START:
232 if (DURATION(u) == 2) { 243 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
233 data->toggle = IS_PULSE(u); 244 break;
234 data->last_unit = u; 245
235 data->state = STATE_TOGGLE_END; 246 data->toggle = ev.pulse;
236 return 0; 247 data->prev_ev = ev;
237 } 248 data->state = STATE_TOGGLE_END;
238 break; 249 return 0;
239 250
240 case STATE_TOGGLE_END: 251 case STATE_TOGGLE_END:
241 if (IS_TRANSITION(u, data->last_unit) && DURATION(u) >= 2) { 252 if (!is_transition(&ev, &data->prev_ev) ||
242 data->state = STATE_BODY_BIT_START; 253 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
243 data->last_unit = u; 254 break;
244 DECREASE_DURATION(u, 2);
245 data->count = 0;
246 255
247 if (!(data->header & RC6_STARTBIT_MASK)) { 256 if (!(data->header & RC6_STARTBIT_MASK)) {
248 IR_dprintk(1, "RC6 invalid start bit\n"); 257 IR_dprintk(1, "RC6 invalid start bit\n");
249 break; 258 break;
250 } 259 }
251 260
252 switch (rc6_mode(data)) { 261 data->state = STATE_BODY_BIT_START;
253 case RC6_MODE_0: 262 data->prev_ev = ev;
254 data->wanted_bits = RC6_0_NBITS; 263 decrease_duration(&ev, RC6_TOGGLE_END);
255 break; 264 data->count = 0;
256 case RC6_MODE_6A: 265
257 /* This might look weird, but we basically 266 switch (rc6_mode(data)) {
258 check the value of the first body bit to 267 case RC6_MODE_0:
259 determine the number of bits in mode 6A */ 268 data->wanted_bits = RC6_0_NBITS;
260 if ((DURATION(u) == 0 && IS_SPACE(data->last_unit)) || DURATION(u) > 0) 269 break;
261 data->wanted_bits = RC6_6A_LARGE_NBITS; 270 case RC6_MODE_6A:
262 else 271 /* This might look weird, but we basically
263 data->wanted_bits = RC6_6A_SMALL_NBITS; 272 check the value of the first body bit to
264 break; 273 determine the number of bits in mode 6A */
265 default: 274 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
266 IR_dprintk(1, "RC6 unknown mode\n"); 275 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
267 goto out; 276 data->wanted_bits = RC6_6A_LARGE_NBITS;
268 } 277 else
269 goto again; 278 data->wanted_bits = RC6_6A_SMALL_NBITS;
279 break;
280 default:
281 IR_dprintk(1, "RC6 unknown mode\n");
282 goto out;
270 } 283 }
271 break; 284 goto again;
272 285
273 case STATE_BODY_BIT_START: 286 case STATE_BODY_BIT_START:
274 if (DURATION(u) == 1) { 287 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
275 data->body <<= 1; 288 break;
276 if (IS_PULSE(u))
277 data->body |= 1;
278 data->count++;
279 data->last_unit = u;
280
281 /*
282 * If the last bit is one, a space will merge
283 * with the silence after the command.
284 */
285 if (IS_PULSE(u) && data->count == data->wanted_bits) {
286 data->state = STATE_FINISHED;
287 goto again;
288 }
289 289
290 data->state = STATE_BODY_BIT_END; 290 data->body <<= 1;
291 return 0; 291 if (ev.pulse)
292 } 292 data->body |= 1;
293 break; 293 data->count++;
294 data->prev_ev = ev;
295
296 data->state = STATE_BODY_BIT_END;
297 return 0;
294 298
295 case STATE_BODY_BIT_END: 299 case STATE_BODY_BIT_END:
296 if (IS_TRANSITION(u, data->last_unit)) { 300 if (!is_transition(&ev, &data->prev_ev))
297 if (data->count == data->wanted_bits) 301 break;
298 data->state = STATE_FINISHED;
299 else
300 data->state = STATE_BODY_BIT_START;
301 302
302 DECREASE_DURATION(u, 1); 303 if (data->count == data->wanted_bits)
303 goto again; 304 data->state = STATE_FINISHED;
304 } 305 else
305 break; 306 data->state = STATE_BODY_BIT_START;
307
308 decrease_duration(&ev, RC6_BIT_END);
309 goto again;
306 310
307 case STATE_FINISHED: 311 case STATE_FINISHED:
312 if (ev.pulse)
313 break;
314
308 switch (rc6_mode(data)) { 315 switch (rc6_mode(data)) {
309 case RC6_MODE_0: 316 case RC6_MODE_0:
310 scancode = data->body & 0xffff; 317 scancode = data->body & 0xffff;
@@ -335,8 +342,8 @@ again:
335 } 342 }
336 343
337out: 344out:
338 IR_dprintk(1, "RC6 decode failed at state %i (%i units, %ius)\n", 345 IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
339 data->state, u, TO_US(duration)); 346 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
340 data->state = STATE_INACTIVE; 347 data->state = STATE_INACTIVE;
341 return -EINVAL; 348 return -EINVAL;
342} 349}