Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[pandora-kernel.git] / drivers / media / IR / ir-rc6-decoder.c
1 /* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
2  *
3  * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
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 "ir-core-priv.h"
16
17 /*
18  * This decoder currently supports:
19  * RC6-0-16     (standard toggle bit in header)
20  * RC6-6A-24    (no toggle bit)
21  * RC6-6A-32    (MCE version with toggle bit in body)
22  */
23
24 #define RC6_UNIT                444444  /* us */
25 #define RC6_HEADER_NBITS        4       /* not including toggle bit */
26 #define RC6_0_NBITS             16
27 #define RC6_6A_SMALL_NBITS      24
28 #define RC6_6A_LARGE_NBITS      32
29 #define RC6_PREFIX_PULSE        (6 * RC6_UNIT)
30 #define RC6_PREFIX_SPACE        (2 * RC6_UNIT)
31 #define RC6_BIT_START           (1 * RC6_UNIT)
32 #define RC6_BIT_END             (1 * RC6_UNIT)
33 #define RC6_TOGGLE_START        (2 * RC6_UNIT)
34 #define RC6_TOGGLE_END          (2 * RC6_UNIT)
35 #define RC6_MODE_MASK           0x07    /* for the header bits */
36 #define RC6_STARTBIT_MASK       0x08    /* for the header bits */
37 #define RC6_6A_MCE_TOGGLE_MASK  0x8000  /* for the body bits */
38
39 enum rc6_mode {
40         RC6_MODE_0,
41         RC6_MODE_6A,
42         RC6_MODE_UNKNOWN,
43 };
44
45 enum rc6_state {
46         STATE_INACTIVE,
47         STATE_PREFIX_SPACE,
48         STATE_HEADER_BIT_START,
49         STATE_HEADER_BIT_END,
50         STATE_TOGGLE_START,
51         STATE_TOGGLE_END,
52         STATE_BODY_BIT_START,
53         STATE_BODY_BIT_END,
54         STATE_FINISHED,
55 };
56
57 static enum rc6_mode rc6_mode(struct rc6_dec *data)
58 {
59         switch (data->header & RC6_MODE_MASK) {
60         case 0:
61                 return RC6_MODE_0;
62         case 6:
63                 if (!data->toggle)
64                         return RC6_MODE_6A;
65                 /* fall through */
66         default:
67                 return RC6_MODE_UNKNOWN;
68         }
69 }
70
71 /**
72  * ir_rc6_decode() - Decode one RC6 pulse or space
73  * @input_dev:  the struct input_dev descriptor of the device
74  * @ev:         the struct ir_raw_event descriptor of the pulse/space
75  *
76  * This function returns -EINVAL if the pulse violates the state machine
77  */
78 static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
79 {
80         struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
81         struct rc6_dec *data = &ir_dev->raw->rc6;
82         u32 scancode;
83         u8 toggle;
84
85         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
86                 return 0;
87
88         if (!is_timing_event(ev)) {
89                 if (ev.reset)
90                         data->state = STATE_INACTIVE;
91                 return 0;
92         }
93
94         if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
95                 goto out;
96
97 again:
98         IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
99                    data->state, TO_US(ev.duration), TO_STR(ev.pulse));
100
101         if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
102                 return 0;
103
104         switch (data->state) {
105
106         case STATE_INACTIVE:
107                 if (!ev.pulse)
108                         break;
109
110                 /* Note: larger margin on first pulse since each RC6_UNIT
111                    is quite short and some hardware takes some time to
112                    adjust to the signal */
113                 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
114                         break;
115
116                 data->state = STATE_PREFIX_SPACE;
117                 data->count = 0;
118                 return 0;
119
120         case STATE_PREFIX_SPACE:
121                 if (ev.pulse)
122                         break;
123
124                 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
125                         break;
126
127                 data->state = STATE_HEADER_BIT_START;
128                 return 0;
129
130         case STATE_HEADER_BIT_START:
131                 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
132                         break;
133
134                 data->header <<= 1;
135                 if (ev.pulse)
136                         data->header |= 1;
137                 data->count++;
138                 data->state = STATE_HEADER_BIT_END;
139                 return 0;
140
141         case STATE_HEADER_BIT_END:
142                 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
143                         break;
144
145                 if (data->count == RC6_HEADER_NBITS)
146                         data->state = STATE_TOGGLE_START;
147                 else
148                         data->state = STATE_HEADER_BIT_START;
149
150                 decrease_duration(&ev, RC6_BIT_END);
151                 goto again;
152
153         case STATE_TOGGLE_START:
154                 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
155                         break;
156
157                 data->toggle = ev.pulse;
158                 data->state = STATE_TOGGLE_END;
159                 return 0;
160
161         case STATE_TOGGLE_END:
162                 if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
163                     !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
164                         break;
165
166                 if (!(data->header & RC6_STARTBIT_MASK)) {
167                         IR_dprintk(1, "RC6 invalid start bit\n");
168                         break;
169                 }
170
171                 data->state = STATE_BODY_BIT_START;
172                 decrease_duration(&ev, RC6_TOGGLE_END);
173                 data->count = 0;
174
175                 switch (rc6_mode(data)) {
176                 case RC6_MODE_0:
177                         data->wanted_bits = RC6_0_NBITS;
178                         break;
179                 case RC6_MODE_6A:
180                         /* This might look weird, but we basically
181                            check the value of the first body bit to
182                            determine the number of bits in mode 6A */
183                         if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
184                             geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
185                                 data->wanted_bits = RC6_6A_LARGE_NBITS;
186                         else
187                                 data->wanted_bits = RC6_6A_SMALL_NBITS;
188                         break;
189                 default:
190                         IR_dprintk(1, "RC6 unknown mode\n");
191                         goto out;
192                 }
193                 goto again;
194
195         case STATE_BODY_BIT_START:
196                 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
197                         break;
198
199                 data->body <<= 1;
200                 if (ev.pulse)
201                         data->body |= 1;
202                 data->count++;
203                 data->state = STATE_BODY_BIT_END;
204                 return 0;
205
206         case STATE_BODY_BIT_END:
207                 if (!is_transition(&ev, &ir_dev->raw->prev_ev))
208                         break;
209
210                 if (data->count == data->wanted_bits)
211                         data->state = STATE_FINISHED;
212                 else
213                         data->state = STATE_BODY_BIT_START;
214
215                 decrease_duration(&ev, RC6_BIT_END);
216                 goto again;
217
218         case STATE_FINISHED:
219                 if (ev.pulse)
220                         break;
221
222                 switch (rc6_mode(data)) {
223                 case RC6_MODE_0:
224                         scancode = data->body & 0xffff;
225                         toggle = data->toggle;
226                         IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
227                                    scancode, toggle);
228                         break;
229                 case RC6_MODE_6A:
230                         if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
231                                 toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
232                                 scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
233                         } else {
234                                 toggle = 0;
235                                 scancode = data->body & 0xffffff;
236                         }
237
238                         IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
239                                    scancode, toggle);
240                         break;
241                 default:
242                         IR_dprintk(1, "RC6 unknown mode\n");
243                         goto out;
244                 }
245
246                 ir_keydown(input_dev, scancode, toggle);
247                 data->state = STATE_INACTIVE;
248                 return 0;
249         }
250
251 out:
252         IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
253                    data->state, TO_US(ev.duration), TO_STR(ev.pulse));
254         data->state = STATE_INACTIVE;
255         return -EINVAL;
256 }
257
258 static struct ir_raw_handler rc6_handler = {
259         .protocols      = IR_TYPE_RC6,
260         .decode         = ir_rc6_decode,
261 };
262
263 static int __init ir_rc6_decode_init(void)
264 {
265         ir_raw_handler_register(&rc6_handler);
266
267         printk(KERN_INFO "IR RC6 protocol handler initialized\n");
268         return 0;
269 }
270
271 static void __exit ir_rc6_decode_exit(void)
272 {
273         ir_raw_handler_unregister(&rc6_handler);
274 }
275
276 module_init(ir_rc6_decode_init);
277 module_exit(ir_rc6_decode_exit);
278
279 MODULE_LICENSE("GPL");
280 MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
281 MODULE_DESCRIPTION("RC6 IR protocol decoder");