aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-nec-decoder.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-04-08 12:10:00 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:57:03 -0400
commit724e2495502a98aaa3f93c404472a991da8ff857 (patch)
treedfdc90b4408fa95f7757b1c6e5b36c2789da0df2 /drivers/media/IR/ir-nec-decoder.c
parentd22e546ea18ee66c255af906f2714d3ee82d4b42 (diff)
V4L/DVB: Teach drivers/media/IR/ir-raw-event.c to use durations
drivers/media/IR/ir-raw-event.c is currently written with the assumption that all "raw" hardware will generate events only on state change (i.e. when a pulse or space starts). However, some hardware (like mceusb, probably the most popular IR receiver out there) only generates duration data (and that data is buffered so using any kind of timing on the data is futile). Furthermore, using signed int's to represent pulse/space durations is a well-known approach when writing ir decoders. With this patch: - s64 int's are used to represent pulse/space durations in ns - a workqueue is used to decode the ir protocols outside of interrupt context - #defines are added to make decoders clearer - decoder reset is implemented by passing a zero duration to the kfifo queue and decoders are updated accordingly 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-nec-decoder.c')
-rw-r--r--drivers/media/IR/ir-nec-decoder.c247
1 files changed, 98 insertions, 149 deletions
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 18918e52c0c0..02682e617fae 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -13,15 +13,16 @@
13 */ 13 */
14 14
15#include <media/ir-core.h> 15#include <media/ir-core.h>
16#include <linux/bitrev.h>
16 17
17#define NEC_NBITS 32 18#define NEC_NBITS 32
18#define NEC_UNIT 559979 /* ns */ 19#define NEC_UNIT 562500 /* ns */
19#define NEC_HEADER_MARK (16 * NEC_UNIT) 20#define NEC_HEADER_PULSE PULSE(16)
20#define NEC_HEADER_SPACE (8 * NEC_UNIT) 21#define NEC_HEADER_SPACE SPACE(8)
21#define NEC_REPEAT_SPACE (4 * NEC_UNIT) 22#define NEC_REPEAT_SPACE SPACE(4)
22#define NEC_MARK (NEC_UNIT) 23#define NEC_BIT_PULSE PULSE(1)
23#define NEC_0_SPACE (NEC_UNIT) 24#define NEC_BIT_0_SPACE SPACE(1)
24#define NEC_1_SPACE (3 * NEC_UNIT) 25#define NEC_BIT_1_SPACE SPACE(3)
25 26
26/* Used to register nec_decoder clients */ 27/* Used to register nec_decoder clients */
27static LIST_HEAD(decoder_list); 28static LIST_HEAD(decoder_list);
@@ -29,21 +30,13 @@ static DEFINE_SPINLOCK(decoder_lock);
29 30
30enum nec_state { 31enum nec_state {
31 STATE_INACTIVE, 32 STATE_INACTIVE,
32 STATE_HEADER_MARK,
33 STATE_HEADER_SPACE, 33 STATE_HEADER_SPACE,
34 STATE_MARK, 34 STATE_BIT_PULSE,
35 STATE_SPACE, 35 STATE_BIT_SPACE,
36 STATE_TRAILER_MARK, 36 STATE_TRAILER_PULSE,
37 STATE_TRAILER_SPACE, 37 STATE_TRAILER_SPACE,
38}; 38};
39 39
40struct nec_code {
41 u8 address;
42 u8 not_address;
43 u8 command;
44 u8 not_command;
45};
46
47struct decoder_data { 40struct decoder_data {
48 struct list_head list; 41 struct list_head list;
49 struct ir_input_dev *ir_dev; 42 struct ir_input_dev *ir_dev;
@@ -51,7 +44,7 @@ struct decoder_data {
51 44
52 /* State machine control */ 45 /* State machine control */
53 enum nec_state state; 46 enum nec_state state;
54 struct nec_code nec_code; 47 u32 nec_bits;
55 unsigned count; 48 unsigned count;
56}; 49};
57 50
@@ -62,7 +55,6 @@ struct decoder_data {
62 * 55 *
63 * Returns the struct decoder_data that corresponds to a device 56 * Returns the struct decoder_data that corresponds to a device
64 */ 57 */
65
66static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 58static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
67{ 59{
68 struct decoder_data *data = NULL; 60 struct decoder_data *data = NULL;
@@ -123,20 +115,20 @@ static struct attribute_group decoder_attribute_group = {
123 .attrs = decoder_attributes, 115 .attrs = decoder_attributes,
124}; 116};
125 117
126
127/** 118/**
128 * ir_nec_decode() - Decode one NEC pulse or space 119 * ir_nec_decode() - Decode one NEC pulse or space
129 * @input_dev: the struct input_dev descriptor of the device 120 * @input_dev: the struct input_dev descriptor of the device
130 * @ev: event array with type/duration of pulse/space 121 * @duration: duration in ns of pulse/space
131 * 122 *
132 * This function returns -EINVAL if the pulse violates the state machine 123 * This function returns -EINVAL if the pulse violates the state machine
133 */ 124 */
134static int ir_nec_decode(struct input_dev *input_dev, 125static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
135 struct ir_raw_event *ev)
136{ 126{
137 struct decoder_data *data; 127 struct decoder_data *data;
138 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 128 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
139 int bit, last_bit; 129 int u;
130 u32 scancode;
131 u8 address, not_address, command, not_command;
140 132
141 data = get_decoder_data(ir_dev); 133 data = get_decoder_data(ir_dev);
142 if (!data) 134 if (!data)
@@ -145,150 +137,107 @@ static int ir_nec_decode(struct input_dev *input_dev,
145 if (!data->enabled) 137 if (!data->enabled)
146 return 0; 138 return 0;
147 139
148 /* Except for the initial event, what matters is the previous bit */ 140 if (IS_RESET(duration)) {
149 bit = (ev->type & IR_PULSE) ? 1 : 0;
150
151 last_bit = !bit;
152
153 /* Discards spurious space last_bits when inactive */
154
155 /* Very long delays are considered as start events */
156 if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2)
157 data->state = STATE_INACTIVE; 141 data->state = STATE_INACTIVE;
142 return 0;
143 }
158 144
159 if (ev->type & IR_START_EVENT) 145 u = TO_UNITS(duration, NEC_UNIT);
160 data->state = STATE_INACTIVE; 146 if (DURATION(u) == 0)
147 goto out;
148
149 IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n",
150 data->state, u, TO_US(duration));
161 151
162 switch (data->state) { 152 switch (data->state) {
163 case STATE_INACTIVE:
164 if (!bit) /* PULSE marks the start event */
165 return 0;
166 153
167 data->count = 0; 154 case STATE_INACTIVE:
168 data->state = STATE_HEADER_MARK; 155 if (u == NEC_HEADER_PULSE) {
169 memset (&data->nec_code, 0, sizeof(data->nec_code)); 156 data->count = 0;
170 return 0; 157 data->state = STATE_HEADER_SPACE;
171 case STATE_HEADER_MARK: 158 }
172 if (!last_bit)
173 goto err;
174 if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT)
175 goto err;
176 data->state = STATE_HEADER_SPACE;
177 return 0; 159 return 0;
160
178 case STATE_HEADER_SPACE: 161 case STATE_HEADER_SPACE:
179 if (last_bit) 162 if (u == NEC_HEADER_SPACE) {
180 goto err; 163 data->state = STATE_BIT_PULSE;
181 if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) {
182 data->state = STATE_MARK;
183 return 0; 164 return 0;
184 } 165 } else if (u == NEC_REPEAT_SPACE) {
185
186 if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) {
187 ir_repeat(input_dev); 166 ir_repeat(input_dev);
188 IR_dprintk(1, "Repeat last key\n"); 167 IR_dprintk(1, "Repeat last key\n");
189 data->state = STATE_TRAILER_MARK; 168 data->state = STATE_TRAILER_PULSE;
190 return 0; 169 return 0;
191 } 170 }
192 goto err; 171 break;
193 case STATE_MARK: 172
194 if (!last_bit) 173 case STATE_BIT_PULSE:
195 goto err; 174 if (u == NEC_BIT_PULSE) {
196 if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || 175 data->state = STATE_BIT_SPACE;
197 (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) 176 return 0;
198 goto err; 177 }
199 data->state = STATE_SPACE; 178 break;
200 return 0; 179
201 case STATE_SPACE: 180 case STATE_BIT_SPACE:
202 if (last_bit) 181 if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE)
203 goto err; 182 break;
204 183
205 if ((ev->delta.tv_nsec >= NEC_0_SPACE - NEC_UNIT / 2) && 184 data->nec_bits <<= 1;
206 (ev->delta.tv_nsec < NEC_0_SPACE + NEC_UNIT / 2)) 185 if (u == NEC_BIT_1_SPACE)
207 bit = 0; 186 data->nec_bits |= 1;
208 else if ((ev->delta.tv_nsec >= NEC_1_SPACE - NEC_UNIT / 2) && 187 data->count++;
209 (ev->delta.tv_nsec < NEC_1_SPACE + NEC_UNIT / 2)) 188
210 bit = 1; 189 if (data->count != NEC_NBITS) {
211 else { 190 data->state = STATE_BIT_PULSE;
212 IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", 191 return 0;
213 data->count, 192 }
214 last_bit ? "pulse" : "space", 193
215 (ev->delta.tv_nsec + 500) / 1000); 194 address = bitrev8((data->nec_bits >> 24) & 0xff);
216 195 not_address = bitrev8((data->nec_bits >> 16) & 0xff);
217 goto err2; 196 command = bitrev8((data->nec_bits >> 8) & 0xff);
197 not_command = bitrev8((data->nec_bits >> 0) & 0xff);
198
199 if ((command ^ not_command) != 0xff) {
200 IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
201 data->nec_bits);
202 break;
218 } 203 }
219 204
220 /* Ok, we've got a valid bit. proccess it */ 205 if ((address ^ not_address) != 0xff) {
221 if (bit) { 206 /* Extended NEC */
222 int shift = data->count; 207 scancode = address << 16 |
223 208 not_address << 8 |
224 /* 209 command;
225 * NEC transmit bytes on this temporal order: 210 IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
226 * address | not address | command | not command 211 } else {
227 */ 212 /* normal NEC */
228 if (shift < 8) { 213 scancode = address << 8 | command;
229 data->nec_code.address |= 1 << shift; 214 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
230 } else if (shift < 16) {
231 data->nec_code.not_address |= 1 << (shift - 8);
232 } else if (shift < 24) {
233 data->nec_code.command |= 1 << (shift - 16);
234 } else {
235 data->nec_code.not_command |= 1 << (shift - 24);
236 }
237 } 215 }
238 if (++data->count == NEC_NBITS) { 216
239 u32 scancode; 217 ir_keydown(input_dev, scancode, 0);
240 /* 218 data->state = STATE_TRAILER_PULSE;
241 * Fixme: may need to accept Extended NEC protocol?
242 */
243 if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff)
244 goto checksum_err;
245
246 if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) {
247 /* Extended NEC */
248 scancode = data->nec_code.address << 16 |
249 data->nec_code.not_address << 8 |
250 data->nec_code.command;
251 IR_dprintk(1, "NEC scancode 0x%06x\n", scancode);
252 } else {
253 /* normal NEC */
254 scancode = data->nec_code.address << 8 |
255 data->nec_code.command;
256 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
257 }
258 ir_keydown(input_dev, scancode, 0);
259
260 data->state = STATE_TRAILER_MARK;
261 } else
262 data->state = STATE_MARK;
263 return 0;
264 case STATE_TRAILER_MARK:
265 if (!last_bit)
266 goto err;
267 data->state = STATE_TRAILER_SPACE;
268 return 0; 219 return 0;
220
221 case STATE_TRAILER_PULSE:
222 if (u > 0) {
223 data->state = STATE_TRAILER_SPACE;
224 return 0;
225 }
226 break;
227
269 case STATE_TRAILER_SPACE: 228 case STATE_TRAILER_SPACE:
270 if (last_bit) 229 if (u < 0) {
271 goto err; 230 data->state = STATE_INACTIVE;
272 data->state = STATE_INACTIVE; 231 return 0;
273 return 0; 232 }
274 }
275 233
276err: 234 break;
277 IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", 235 }
278 data->state,
279 bit ? "pulse" : "space",
280 (ev->delta.tv_nsec + 500) / 1000);
281err2:
282 data->state = STATE_INACTIVE;
283 return -EINVAL;
284 236
285checksum_err: 237out:
238 IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n",
239 data->state, u, TO_US(duration));
286 data->state = STATE_INACTIVE; 240 data->state = STATE_INACTIVE;
287 IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n",
288 data->nec_code.address,
289 data->nec_code.not_address,
290 data->nec_code.command,
291 data->nec_code.not_command);
292 return -EINVAL; 241 return -EINVAL;
293} 242}
294 243