Commit | Line | Data |
---|---|---|
d15549ac RC |
1 | /* |
2 | * | |
3 | * some common structs and functions to handle infrared remotes via | |
4 | * input layer ... | |
5 | * | |
6 | * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | */ | |
22 | ||
23 | #include <linux/module.h> | |
d15549ac | 24 | #include <linux/string.h> |
0b778a56 | 25 | #include <linux/jiffies.h> |
d15549ac RC |
26 | #include <media/ir-common.h> |
27 | ||
28 | /* -------------------------------------------------------------------------- */ | |
29 | ||
30 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | |
31 | MODULE_LICENSE("GPL"); | |
32 | ||
33 | static int repeat = 1; | |
34 | module_param(repeat, int, 0444); | |
35 | MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); | |
36 | ||
ff699e6b | 37 | static int debug; /* debug level (0,1,2) */ |
d15549ac RC |
38 | module_param(debug, int, 0644); |
39 | ||
40 | #define dprintk(level, fmt, arg...) if (debug >= level) \ | |
41 | printk(KERN_DEBUG fmt , ## arg) | |
42 | ||
43 | /* -------------------------------------------------------------------------- */ | |
44 | ||
45 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | |
46 | { | |
47 | if (KEY_RESERVED == ir->keycode) { | |
48 | printk(KERN_INFO "%s: unknown key: key=0x%02x raw=0x%02x down=%d\n", | |
49 | dev->name,ir->ir_key,ir->ir_raw,ir->keypressed); | |
50 | return; | |
51 | } | |
52 | dprintk(1,"%s: key event code=%d down=%d\n", | |
53 | dev->name,ir->keycode,ir->keypressed); | |
54 | input_report_key(dev,ir->keycode,ir->keypressed); | |
55 | input_sync(dev); | |
56 | } | |
57 | ||
58 | /* -------------------------------------------------------------------------- */ | |
59 | ||
60 | void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | |
715a2233 | 61 | int ir_type, struct ir_scancode_table *ir_codes) |
d15549ac RC |
62 | { |
63 | int i; | |
64 | ||
65 | ir->ir_type = ir_type; | |
715a2233 | 66 | |
361c9511 | 67 | memset(ir->ir_codes, 0, sizeof(ir->ir_codes)); |
715a2233 MCC |
68 | |
69 | /* | |
70 | * FIXME: This is a temporary workaround to use the new IR tables | |
71 | * with the old approach. Later patches will replace this to a | |
72 | * proper method | |
73 | */ | |
74 | ||
d15549ac | 75 | if (ir_codes) |
715a2233 MCC |
76 | for (i = 0; i < ir_codes->size; i++) |
77 | if (ir_codes->scan[i].scancode < IR_KEYTAB_SIZE) | |
78 | ir->ir_codes[ir_codes->scan[i].scancode] = ir_codes->scan[i].keycode; | |
d15549ac | 79 | |
d15549ac RC |
80 | dev->keycode = ir->ir_codes; |
81 | dev->keycodesize = sizeof(IR_KEYTAB_TYPE); | |
82 | dev->keycodemax = IR_KEYTAB_SIZE; | |
83 | for (i = 0; i < IR_KEYTAB_SIZE; i++) | |
84 | set_bit(ir->ir_codes[i], dev->keybit); | |
85 | clear_bit(0, dev->keybit); | |
86 | ||
87 | set_bit(EV_KEY, dev->evbit); | |
88 | if (repeat) | |
89 | set_bit(EV_REP, dev->evbit); | |
90 | } | |
4db16db4 | 91 | EXPORT_SYMBOL_GPL(ir_input_init); |
d15549ac RC |
92 | |
93 | void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) | |
94 | { | |
95 | if (ir->keypressed) { | |
96 | ir->keypressed = 0; | |
97 | ir_input_key_event(dev,ir); | |
98 | } | |
99 | } | |
4db16db4 | 100 | EXPORT_SYMBOL_GPL(ir_input_nokey); |
d15549ac RC |
101 | |
102 | void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, | |
103 | u32 ir_key, u32 ir_raw) | |
104 | { | |
105 | u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key); | |
106 | ||
107 | if (ir->keypressed && ir->keycode != keycode) { | |
108 | ir->keypressed = 0; | |
109 | ir_input_key_event(dev,ir); | |
110 | } | |
111 | if (!ir->keypressed) { | |
112 | ir->ir_key = ir_key; | |
113 | ir->ir_raw = ir_raw; | |
114 | ir->keycode = keycode; | |
115 | ir->keypressed = 1; | |
116 | ir_input_key_event(dev,ir); | |
117 | } | |
118 | } | |
4db16db4 | 119 | EXPORT_SYMBOL_GPL(ir_input_keydown); |
d15549ac RC |
120 | |
121 | /* -------------------------------------------------------------------------- */ | |
d67be61e | 122 | /* extract mask bits out of data and pack them into the result */ |
d15549ac RC |
123 | u32 ir_extract_bits(u32 data, u32 mask) |
124 | { | |
d67be61e TP |
125 | u32 vbit = 1, value = 0; |
126 | ||
127 | do { | |
128 | if (mask&1) { | |
129 | if (data&1) | |
130 | value |= vbit; | |
131 | vbit<<=1; | |
132 | } | |
133 | data>>=1; | |
134 | } while (mask>>=1); | |
135 | ||
d15549ac RC |
136 | return value; |
137 | } | |
4db16db4 | 138 | EXPORT_SYMBOL_GPL(ir_extract_bits); |
d15549ac RC |
139 | |
140 | static int inline getbit(u32 *samples, int bit) | |
141 | { | |
142 | return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; | |
143 | } | |
144 | ||
145 | /* sump raw samples for visual debugging ;) */ | |
146 | int ir_dump_samples(u32 *samples, int count) | |
147 | { | |
148 | int i, bit, start; | |
149 | ||
150 | printk(KERN_DEBUG "ir samples: "); | |
151 | start = 0; | |
152 | for (i = 0; i < count * 32; i++) { | |
153 | bit = getbit(samples,i); | |
154 | if (bit) | |
155 | start = 1; | |
156 | if (0 == start) | |
157 | continue; | |
158 | printk("%s", bit ? "#" : "_"); | |
159 | } | |
160 | printk("\n"); | |
161 | return 0; | |
162 | } | |
4db16db4 | 163 | EXPORT_SYMBOL_GPL(ir_dump_samples); |
d15549ac RC |
164 | |
165 | /* decode raw samples, pulse distance coding used by NEC remotes */ | |
166 | int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) | |
167 | { | |
168 | int i,last,bit,len; | |
169 | u32 curBit; | |
170 | u32 value; | |
171 | ||
172 | /* find start burst */ | |
173 | for (i = len = 0; i < count * 32; i++) { | |
174 | bit = getbit(samples,i); | |
175 | if (bit) { | |
176 | len++; | |
177 | } else { | |
178 | if (len >= 29) | |
179 | break; | |
180 | len = 0; | |
181 | } | |
182 | } | |
183 | ||
184 | /* start burst to short */ | |
185 | if (len < 29) | |
186 | return 0xffffffff; | |
187 | ||
188 | /* find start silence */ | |
189 | for (len = 0; i < count * 32; i++) { | |
190 | bit = getbit(samples,i); | |
191 | if (bit) { | |
192 | break; | |
193 | } else { | |
194 | len++; | |
195 | } | |
196 | } | |
197 | ||
198 | /* silence to short */ | |
199 | if (len < 7) | |
200 | return 0xffffffff; | |
201 | ||
202 | /* go decoding */ | |
203 | len = 0; | |
204 | last = 1; | |
205 | value = 0; curBit = 1; | |
206 | for (; i < count * 32; i++) { | |
207 | bit = getbit(samples,i); | |
208 | if (last) { | |
209 | if(bit) { | |
210 | continue; | |
211 | } else { | |
212 | len = 1; | |
213 | } | |
214 | } else { | |
215 | if (bit) { | |
216 | if (len > (low + high) /2) | |
217 | value |= curBit; | |
218 | curBit <<= 1; | |
219 | if (curBit == 1) | |
220 | break; | |
221 | } else { | |
222 | len++; | |
223 | } | |
224 | } | |
225 | last = bit; | |
226 | } | |
227 | ||
228 | return value; | |
229 | } | |
4db16db4 | 230 | EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); |
d15549ac RC |
231 | |
232 | /* decode raw samples, biphase coding, used by rc5 for example */ | |
233 | int ir_decode_biphase(u32 *samples, int count, int low, int high) | |
234 | { | |
235 | int i,last,bit,len,flips; | |
236 | u32 value; | |
237 | ||
238 | /* find start bit (1) */ | |
239 | for (i = 0; i < 32; i++) { | |
240 | bit = getbit(samples,i); | |
241 | if (bit) | |
242 | break; | |
243 | } | |
244 | ||
245 | /* go decoding */ | |
246 | len = 0; | |
247 | flips = 0; | |
248 | value = 1; | |
249 | for (; i < count * 32; i++) { | |
250 | if (len > high) | |
251 | break; | |
252 | if (flips > 1) | |
253 | break; | |
254 | last = bit; | |
255 | bit = getbit(samples,i); | |
256 | if (last == bit) { | |
257 | len++; | |
258 | continue; | |
259 | } | |
260 | if (len < low) { | |
261 | len++; | |
262 | flips++; | |
263 | continue; | |
264 | } | |
265 | value <<= 1; | |
266 | value |= bit; | |
267 | flips = 0; | |
268 | len = 1; | |
269 | } | |
270 | return value; | |
271 | } | |
4db16db4 | 272 | EXPORT_SYMBOL_GPL(ir_decode_biphase); |
d15549ac | 273 | |
9160723e HP |
274 | /* RC5 decoding stuff, moved from bttv-input.c to share it with |
275 | * saa7134 */ | |
276 | ||
277 | /* decode raw bit pattern to RC5 code */ | |
9695a498 | 278 | static u32 ir_rc5_decode(unsigned int code) |
9160723e HP |
279 | { |
280 | unsigned int org_code = code; | |
281 | unsigned int pair; | |
282 | unsigned int rc5 = 0; | |
283 | int i; | |
284 | ||
285 | for (i = 0; i < 14; ++i) { | |
286 | pair = code & 0x3; | |
287 | code >>= 2; | |
288 | ||
289 | rc5 <<= 1; | |
290 | switch (pair) { | |
291 | case 0: | |
292 | case 2: | |
293 | break; | |
294 | case 1: | |
295 | rc5 |= 1; | |
296 | break; | |
297 | case 3: | |
298 | dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); | |
299 | return 0; | |
300 | } | |
301 | } | |
302 | dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | |
303 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | |
304 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | |
305 | return rc5; | |
306 | } | |
307 | ||
308 | void ir_rc5_timer_end(unsigned long data) | |
309 | { | |
310 | struct card_ir *ir = (struct card_ir *)data; | |
311 | struct timeval tv; | |
312 | unsigned long current_jiffies, timeout; | |
313 | u32 gap; | |
314 | u32 rc5 = 0; | |
315 | ||
316 | /* get time */ | |
317 | current_jiffies = jiffies; | |
318 | do_gettimeofday(&tv); | |
319 | ||
320 | /* avoid overflow with gap >1s */ | |
321 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | |
322 | gap = 200000; | |
323 | } else { | |
324 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | |
325 | tv.tv_usec - ir->base_time.tv_usec; | |
326 | } | |
327 | ||
726cf56f VP |
328 | /* signal we're ready to start a new code */ |
329 | ir->active = 0; | |
330 | ||
331 | /* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ | |
9160723e HP |
332 | if (gap < 28000) { |
333 | dprintk(1, "ir-common: spurious timer_end\n"); | |
334 | return; | |
335 | } | |
336 | ||
9160723e HP |
337 | if (ir->last_bit < 20) { |
338 | /* ignore spurious codes (caused by light/other remotes) */ | |
339 | dprintk(1, "ir-common: short code: %x\n", ir->code); | |
340 | } else { | |
341 | ir->code = (ir->code << ir->shift_by) | 1; | |
342 | rc5 = ir_rc5_decode(ir->code); | |
343 | ||
344 | /* two start bits? */ | |
345 | if (RC5_START(rc5) != ir->start) { | |
346 | dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); | |
347 | ||
348 | /* right address? */ | |
349 | } else if (RC5_ADDR(rc5) == ir->addr) { | |
350 | u32 toggle = RC5_TOGGLE(rc5); | |
351 | u32 instr = RC5_INSTR(rc5); | |
352 | ||
353 | /* Good code, decide if repeat/repress */ | |
354 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | |
355 | instr != RC5_INSTR(ir->last_rc5)) { | |
356 | dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, | |
357 | toggle); | |
358 | ir_input_nokey(ir->dev, &ir->ir); | |
359 | ir_input_keydown(ir->dev, &ir->ir, instr, | |
360 | instr); | |
361 | } | |
362 | ||
363 | /* Set/reset key-up timer */ | |
f7518bd2 MCC |
364 | timeout = current_jiffies + |
365 | msecs_to_jiffies(ir->rc5_key_timeout); | |
9160723e HP |
366 | mod_timer(&ir->timer_keyup, timeout); |
367 | ||
368 | /* Save code for repeat test */ | |
369 | ir->last_rc5 = rc5; | |
370 | } | |
371 | } | |
372 | } | |
4db16db4 | 373 | EXPORT_SYMBOL_GPL(ir_rc5_timer_end); |
9160723e HP |
374 | |
375 | void ir_rc5_timer_keyup(unsigned long data) | |
376 | { | |
377 | struct card_ir *ir = (struct card_ir *)data; | |
378 | ||
379 | dprintk(1, "ir-common: key released\n"); | |
380 | ir_input_nokey(ir->dev, &ir->ir); | |
381 | } | |
9160723e | 382 | EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); |