diff options
author | David Härdeman <david@hardeman.nu> | 2010-04-08 19:04:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-19 11:57:15 -0400 |
commit | 733419b5c4d29186006982a9a27227e214a39dbc (patch) | |
tree | 78e0fb88a5dbee745d6f5f3c0afd670006628812 /drivers/media/IR/ir-rc5-decoder.c | |
parent | 450df22286eee7431b34644410aeff18936c7afe (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>
Diffstat (limited to 'drivers/media/IR/ir-rc5-decoder.c')
-rw-r--r-- | drivers/media/IR/ir-rc5-decoder.c | 78 |
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 d8f0760890fa..dd5a4d5f25fd 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 | ||
149 | again: | 155 | again: |
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 | ||
215 | out: | 255 | out: |
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); | |||
288 | MODULE_LICENSE("GPL"); | 328 | MODULE_LICENSE("GPL"); |
289 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | 329 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
290 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); | 330 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); |
291 | MODULE_DESCRIPTION("RC-5 IR protocol decoder"); | 331 | MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); |