V4L/DVB: ir-core/saa7134: Move ir keyup/keydown code to 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  * __ir_nec_decode() - Decode one NEC pulsecode
35  * @input_dev:  the struct input_dev descriptor of the device
36  * @evs:        event array with type/duration of pulse/space
37  * @len:        length of the array
38  * @pos:        position to start seeking for a code
39  * This function returns the decoded ircode or -EINVAL if no pulse got decoded
40  */
41 static int __ir_nec_decode(struct input_dev *input_dev,
42                            struct ir_raw_event *evs,
43                            int len, int *pos)
44 {
45         int count = -1;
46         int ircode = 0, not_code = 0;
47
48         /* Be sure that the first event is an start one and is a pulse */
49         for (; *pos < len; (*pos)++) {
50                 if (evs[*pos].type & (IR_START_EVENT | IR_PULSE))
51                         break;
52         }
53         (*pos)++;       /* First event doesn't contain data */
54
55         if (*pos >= len)
56                 return 0;
57
58         /* First space should have 4.5 ms otherwise is not NEC protocol */
59         if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) |
60             (evs[*pos].delta.tv_nsec > MAX_START_TIME) |
61             (evs[*pos].type != IR_SPACE))
62                 goto err;
63
64         /*
65          * FIXME: need to implement the repeat sequence
66          */
67
68         count = 0;
69         for ((*pos)++; *pos < len; (*pos)++) {
70                 int bit;
71
72                 if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) |
73                     (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) |
74                     (evs[*pos].type != IR_PULSE))
75                         goto err;
76
77                 if (++*pos >= len)
78                         goto err;
79                 if (evs[*pos].type != IR_SPACE)
80                         goto err;
81
82                 if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) &&
83                     (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME))
84                         bit = 1;
85                 else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) &&
86                          (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME))
87                         bit = 0;
88                 else
89                         goto err;
90
91                 if (bit) {
92                         int shift = count;
93                         /* Address first, then command */
94                         if (shift < 8) {
95                                 shift += 8;
96                                 ircode |= 1 << shift;
97                         } else if (shift < 16) {
98                                 not_code |= 1 << shift;
99                         } else if (shift < 24) {
100                                 shift -= 16;
101                                 ircode |= 1 << shift;
102                         } else {
103                                 shift -= 24;
104                                 not_code |= 1 << shift;
105                         }
106                 }
107                 if (++count == 32)
108                         break;
109         }
110
111         /*
112          * Fixme: may need to accept Extended NEC protocol?
113          */
114         if ((ircode & ~not_code) != ircode) {
115                 IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n",
116                            ircode, not_code);
117                 return -EINVAL;
118         }
119
120         IR_dprintk(1, "NEC scancode 0x%04x\n", ircode);
121         ir_keydown(input_dev, ircode);
122         ir_keyup(input_dev);
123
124         return ircode;
125 err:
126         IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n",
127                    count, (evs[*pos].delta.tv_nsec + 500) / 1000);
128
129         return -EINVAL;
130 }
131
132 /**
133  * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array
134  * @input_dev:  the struct input_dev descriptor of the device
135  * @evs:        event array with type/duration of pulse/space
136  * @len:        length of the array
137  * This function returns the number of decoded pulses or -EINVAL if no
138  * pulse got decoded
139  */
140 int ir_nec_decode(struct input_dev *input_dev,
141                            struct ir_raw_event *evs,
142                            int len)
143 {
144         int pos = 0;
145         int rc = 0;
146
147         while (pos < len) {
148                 if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0)
149                         rc++;
150         }
151
152         if (!rc)
153                 return -EINVAL;
154         return rc;
155 }
156
157 EXPORT_SYMBOL_GPL(ir_nec_decode);