V4L/DVB: ir-core: Add logic to decode IR protocols at the IR core
[safe/jmp/linux-2.6] / drivers / media / IR / ir-nec-decoder.c
1 /* ir-raw-event.c - handle IR Pulse/Space event
2  *
3  * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14
15 #include <media/ir-core.h>
16
17 /* Start time: 4.5 ms  */
18 #define MIN_START_TIME  3900000
19 #define MAX_START_TIME  5100000
20
21 /* Pulse time: 560 us  */
22 #define MIN_PULSE_TIME  460000
23 #define MAX_PULSE_TIME  660000
24
25 /* Bit 1 space time: 2.25ms-560 us */
26 #define MIN_BIT1_TIME   1490000
27 #define MAX_BIT1_TIME   1890000
28
29 /* Bit 0 space time: 1.12ms-560 us */
30 #define MIN_BIT0_TIME   360000
31 #define MAX_BIT0_TIME   760000
32
33
34 /** Decode NEC pulsecode. This code can take up to 76.5 ms to run.
35         Unfortunately, using IRQ to decode pulse didn't work, since it uses
36         a pulse train of 38KHz. This means one pulse on each 52 us
37 */
38
39 int ir_nec_decode(struct input_dev *input_dev,
40                   struct ir_raw_event *evs,
41                   int len)
42 {
43         int i, count = -1;
44         int ircode = 0, not_code = 0;
45 #if 0
46         /* Needed only after porting the event code to the decoder */
47         struct ir_input_dev *ir = input_get_drvdata(input_dev);
48 #endif
49
50         /* Be sure that the first event is an start one and is a pulse */
51         for (i = 0; i < len; i++) {
52                 if (evs[i].type & (IR_START_EVENT | IR_PULSE))
53                         break;
54         }
55         i++;    /* First event doesn't contain data */
56
57         if (i >= len)
58                 return 0;
59
60         /* First space should have 4.5 ms otherwise is not NEC protocol */
61         if ((evs[i].delta.tv_nsec < MIN_START_TIME) |
62             (evs[i].delta.tv_nsec > MAX_START_TIME) |
63             (evs[i].type != IR_SPACE))
64                 goto err;
65
66         /*
67          * FIXME: need to implement the repeat sequence
68          */
69
70         count = 0;
71         for (i++; i < len; i++) {
72                 int bit;
73
74                 if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) |
75                     (evs[i].delta.tv_nsec > MAX_PULSE_TIME) |
76                     (evs[i].type != IR_PULSE))
77                         goto err;
78
79                 if (++i >= len)
80                         goto err;
81                 if (evs[i].type != IR_SPACE)
82                         goto err;
83
84                 if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) &&
85                     (evs[i].delta.tv_nsec < MAX_BIT1_TIME))
86                         bit = 1;
87                 else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) &&
88                          (evs[i].delta.tv_nsec < MAX_BIT0_TIME))
89                         bit = 0;
90                 else
91                         goto err;
92
93                 if (bit) {
94                         int shift = count;
95                         /* Address first, then command */
96                         if (shift < 8) {
97                                 shift += 8;
98                                 ircode |= 1 << shift;
99                         } else if (shift < 16) {
100                                 not_code |= 1 << shift;
101                         } else if (shift < 24) {
102                                 shift -= 16;
103                                 ircode |= 1 << shift;
104                         } else {
105                                 shift -= 24;
106                                 not_code |= 1 << shift;
107                         }
108                 }
109                 if (++count == 32)
110                         break;
111         }
112
113         /*
114          * Fixme: may need to accept Extended NEC protocol?
115          */
116         if ((ircode & ~not_code) != ircode) {
117                 IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n",
118                            ircode, not_code);
119                 return -EINVAL;
120         }
121
122         IR_dprintk(1, "NEC scancode 0x%04x\n", ircode);
123
124         return ircode;
125 err:
126         IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n",
127                    count, (evs[i].delta.tv_nsec + 500) / 1000);
128
129         return -EINVAL;
130 }
131 EXPORT_SYMBOL_GPL(ir_nec_decode);