aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-04-08 19:04:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:57:15 -0400
commit733419b5c4d29186006982a9a27227e214a39dbc (patch)
tree78e0fb88a5dbee745d6f5f3c0afd670006628812
parent450df22286eee7431b34644410aeff18936c7afe (diff)
V4L/DVB: Add RC5x support to ir-core
This patch adds RC5x support to drivers/media/IR/ir-rc5-decoder.c Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/IR/ir-rc5-decoder.c78
1 files changed, 59 insertions, 19 deletions
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
index d8f0760890f..dd5a4d5f25f 100644
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ b/drivers/media/IR/ir-rc5-decoder.c
@@ -1,4 +1,4 @@
1/* ir-rc5-decoder.c - handle RC-5 IR Pulse/Space protocol 1/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
2 * 2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> 3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 * 4 *
@@ -13,15 +13,19 @@
13 */ 13 */
14 14
15/* 15/*
16 * This code only handles 14 bits RC-5 protocols. There are other variants 16 * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
17 * that use a different number of bits. This is currently unsupported 17 * There are other variants that use a different number of bits.
18 * It considers a carrier of 36 kHz, with a total of 14 bits, where 18 * This is currently unsupported.
19 * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
19 * the first two bits are start bits, and a third one is a filing bit 20 * the first two bits are start bits, and a third one is a filing bit
20 */ 21 */
21 22
22#include "ir-core-priv.h" 23#include "ir-core-priv.h"
23 24
24#define RC5_NBITS 14 25#define RC5_NBITS 14
26#define RC5X_NBITS 20
27#define CHECK_RC5X_NBITS 8
28#define RC5X_SPACE SPACE(4)
25#define RC5_UNIT 888888 /* ns */ 29#define RC5_UNIT 888888 /* ns */
26 30
27/* Used to register rc5_decoder clients */ 31/* Used to register rc5_decoder clients */
@@ -32,6 +36,7 @@ enum rc5_state {
32 STATE_INACTIVE, 36 STATE_INACTIVE,
33 STATE_BIT_START, 37 STATE_BIT_START,
34 STATE_BIT_END, 38 STATE_BIT_END,
39 STATE_CHECK_RC5X,
35 STATE_FINISHED, 40 STATE_FINISHED,
36}; 41};
37 42
@@ -45,6 +50,7 @@ struct decoder_data {
45 u32 rc5_bits; 50 u32 rc5_bits;
46 int last_unit; 51 int last_unit;
47 unsigned count; 52 unsigned count;
53 unsigned wanted_bits;
48}; 54};
49 55
50 56
@@ -126,7 +132,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
126{ 132{
127 struct decoder_data *data; 133 struct decoder_data *data;
128 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 134 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
129 u8 command, system, toggle; 135 u8 toggle;
130 u32 scancode; 136 u32 scancode;
131 int u; 137 int u;
132 138
@@ -147,7 +153,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
147 goto out; 153 goto out;
148 154
149again: 155again:
150 IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", 156 IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n",
151 data->state, u, TO_US(duration)); 157 data->state, u, TO_US(duration));
152 158
153 if (DURATION(u) == 0 && data->state != STATE_FINISHED) 159 if (DURATION(u) == 0 && data->state != STATE_FINISHED)
@@ -159,6 +165,8 @@ again:
159 if (IS_PULSE(u)) { 165 if (IS_PULSE(u)) {
160 data->state = STATE_BIT_START; 166 data->state = STATE_BIT_START;
161 data->count = 1; 167 data->count = 1;
168 /* We just need enough bits to get to STATE_CHECK_RC5X */
169 data->wanted_bits = RC5X_NBITS;
162 DECREASE_DURATION(u, 1); 170 DECREASE_DURATION(u, 1);
163 goto again; 171 goto again;
164 } 172 }
@@ -176,7 +184,7 @@ again:
176 * If the last bit is zero, a space will merge 184 * If the last bit is zero, a space will merge
177 * with the silence after the command. 185 * with the silence after the command.
178 */ 186 */
179 if (IS_PULSE(u) && data->count == RC5_NBITS) { 187 if (IS_PULSE(u) && data->count == data->wanted_bits) {
180 data->state = STATE_FINISHED; 188 data->state = STATE_FINISHED;
181 goto again; 189 goto again;
182 } 190 }
@@ -188,8 +196,10 @@ again:
188 196
189 case STATE_BIT_END: 197 case STATE_BIT_END:
190 if (IS_TRANSITION(u, data->last_unit)) { 198 if (IS_TRANSITION(u, data->last_unit)) {
191 if (data->count == RC5_NBITS) 199 if (data->count == data->wanted_bits)
192 data->state = STATE_FINISHED; 200 data->state = STATE_FINISHED;
201 else if (data->count == CHECK_RC5X_NBITS)
202 data->state = STATE_CHECK_RC5X;
193 else 203 else
194 data->state = STATE_BIT_START; 204 data->state = STATE_BIT_START;
195 205
@@ -198,22 +208,52 @@ again:
198 } 208 }
199 break; 209 break;
200 210
211 case STATE_CHECK_RC5X:
212 if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) {
213 /* RC5X */
214 data->wanted_bits = RC5X_NBITS;
215 DECREASE_DURATION(u, DURATION(RC5X_SPACE));
216 } else {
217 /* RC5 */
218 data->wanted_bits = RC5_NBITS;
219 }
220 data->state = STATE_BIT_START;
221 goto again;
222
201 case STATE_FINISHED: 223 case STATE_FINISHED:
202 command = (data->rc5_bits & 0x0003F) >> 0; 224 if (data->wanted_bits == RC5X_NBITS) {
203 system = (data->rc5_bits & 0x007C0) >> 6; 225 /* RC5X */
204 toggle = (data->rc5_bits & 0x00800) ? 1 : 0; 226 u8 xdata, command, system;
205 command += (data->rc5_bits & 0x01000) ? 0 : 0x40; 227 xdata = (data->rc5_bits & 0x0003F) >> 0;
206 scancode = system << 8 | command; 228 command = (data->rc5_bits & 0x00FC0) >> 6;
207 229 system = (data->rc5_bits & 0x1F000) >> 12;
208 IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", 230 toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
209 scancode, toggle); 231 command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
232 scancode = system << 16 | command << 8 | xdata;
233
234 IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
235 scancode, toggle);
236
237 } else {
238 /* RC5 */
239 u8 command, system;
240 command = (data->rc5_bits & 0x0003F) >> 0;
241 system = (data->rc5_bits & 0x007C0) >> 6;
242 toggle = (data->rc5_bits & 0x00800) ? 1 : 0;
243 command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
244 scancode = system << 8 | command;
245
246 IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
247 scancode, toggle);
248 }
249
210 ir_keydown(input_dev, scancode, toggle); 250 ir_keydown(input_dev, scancode, toggle);
211 data->state = STATE_INACTIVE; 251 data->state = STATE_INACTIVE;
212 return 0; 252 return 0;
213 } 253 }
214 254
215out: 255out:
216 IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", 256 IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n",
217 data->state, u, TO_US(duration)); 257 data->state, u, TO_US(duration));
218 data->state = STATE_INACTIVE; 258 data->state = STATE_INACTIVE;
219 return -EINVAL; 259 return -EINVAL;
@@ -273,7 +313,7 @@ static int __init ir_rc5_decode_init(void)
273{ 313{
274 ir_raw_handler_register(&rc5_handler); 314 ir_raw_handler_register(&rc5_handler);
275 315
276 printk(KERN_INFO "IR RC-5 protocol handler initialized\n"); 316 printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
277 return 0; 317 return 0;
278} 318}
279 319
@@ -288,4 +328,4 @@ module_exit(ir_rc5_decode_exit);
288MODULE_LICENSE("GPL"); 328MODULE_LICENSE("GPL");
289MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); 329MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
290MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 330MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
291MODULE_DESCRIPTION("RC-5 IR protocol decoder"); 331MODULE_DESCRIPTION("RC5(x) IR protocol decoder");