| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 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> | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 24 | #include <linux/string.h> | 
| Mauro Carvalho Chehab | 0b778a5 | 2006-12-27 14:04:09 -0200 | [diff] [blame] | 25 | #include <linux/jiffies.h> | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 26 | #include <media/ir-common.h> | 
| Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 27 | #include "ir-core-priv.h" | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 28 |  | 
 | 29 | /* -------------------------------------------------------------------------- */ | 
 | 30 |  | 
 | 31 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | 
 | 32 | MODULE_LICENSE("GPL"); | 
 | 33 |  | 
 | 34 | static int repeat = 1; | 
 | 35 | module_param(repeat, int, 0444); | 
 | 36 | MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); | 
 | 37 |  | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 38 | /* -------------------------------------------------------------------------- */ | 
 | 39 |  | 
 | 40 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | 
 | 41 | { | 
 | 42 | 	if (KEY_RESERVED == ir->keycode) { | 
| Mauro Carvalho Chehab | 8573b74 | 2009-11-27 22:40:22 -0300 | [diff] [blame] | 43 | 		printk(KERN_INFO "%s: unknown key: key=0x%02x down=%d\n", | 
 | 44 | 		       dev->name, ir->ir_key, ir->keypressed); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 45 | 		return; | 
 | 46 | 	} | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 47 | 	IR_dprintk(1,"%s: key event code=%d down=%d\n", | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 48 | 		dev->name,ir->keycode,ir->keypressed); | 
 | 49 | 	input_report_key(dev,ir->keycode,ir->keypressed); | 
 | 50 | 	input_sync(dev); | 
 | 51 | } | 
 | 52 |  | 
 | 53 | /* -------------------------------------------------------------------------- */ | 
 | 54 |  | 
| Mauro Carvalho Chehab | 055cd55 | 2009-11-29 08:19:59 -0300 | [diff] [blame] | 55 | int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | 
| Mauro Carvalho Chehab | 971e829 | 2009-12-14 13:53:37 -0300 | [diff] [blame] | 56 | 		  const u64 ir_type) | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 57 | { | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 58 | 	ir->ir_type = ir_type; | 
| Mauro Carvalho Chehab | 715a223 | 2009-08-29 14:15:55 -0300 | [diff] [blame] | 59 |  | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 60 | 	if (repeat) | 
 | 61 | 		set_bit(EV_REP, dev->evbit); | 
| Mauro Carvalho Chehab | 055cd55 | 2009-11-29 08:19:59 -0300 | [diff] [blame] | 62 |  | 
 | 63 | 	return 0; | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 64 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 65 | EXPORT_SYMBOL_GPL(ir_input_init); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 66 |  | 
| Mauro Carvalho Chehab | 055cd55 | 2009-11-29 08:19:59 -0300 | [diff] [blame] | 67 |  | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 68 | void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) | 
 | 69 | { | 
 | 70 | 	if (ir->keypressed) { | 
 | 71 | 		ir->keypressed = 0; | 
 | 72 | 		ir_input_key_event(dev,ir); | 
 | 73 | 	} | 
 | 74 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 75 | EXPORT_SYMBOL_GPL(ir_input_nokey); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 76 |  | 
 | 77 | void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, | 
| Mauro Carvalho Chehab | 8573b74 | 2009-11-27 22:40:22 -0300 | [diff] [blame] | 78 | 		      u32 ir_key) | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 79 | { | 
| Mauro Carvalho Chehab | 8573b74 | 2009-11-27 22:40:22 -0300 | [diff] [blame] | 80 | 	u32 keycode = ir_g_keycode_from_table(dev, ir_key); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 81 |  | 
 | 82 | 	if (ir->keypressed && ir->keycode != keycode) { | 
 | 83 | 		ir->keypressed = 0; | 
 | 84 | 		ir_input_key_event(dev,ir); | 
 | 85 | 	} | 
 | 86 | 	if (!ir->keypressed) { | 
 | 87 | 		ir->ir_key  = ir_key; | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 88 | 		ir->keycode = keycode; | 
 | 89 | 		ir->keypressed = 1; | 
 | 90 | 		ir_input_key_event(dev,ir); | 
 | 91 | 	} | 
 | 92 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 93 | EXPORT_SYMBOL_GPL(ir_input_keydown); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 94 |  | 
 | 95 | /* -------------------------------------------------------------------------- */ | 
| Trent Piepho | d67be61 | 2007-07-11 20:28:44 -0300 | [diff] [blame] | 96 | /* extract mask bits out of data and pack them into the result */ | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 97 | u32 ir_extract_bits(u32 data, u32 mask) | 
 | 98 | { | 
| Trent Piepho | d67be61 | 2007-07-11 20:28:44 -0300 | [diff] [blame] | 99 | 	u32 vbit = 1, value = 0; | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 100 |  | 
| Trent Piepho | d67be61 | 2007-07-11 20:28:44 -0300 | [diff] [blame] | 101 | 	do { | 
 | 102 | 	    if (mask&1) { | 
 | 103 | 		if (data&1) | 
 | 104 | 			value |= vbit; | 
 | 105 | 		vbit<<=1; | 
 | 106 | 	    } | 
 | 107 | 	    data>>=1; | 
 | 108 | 	} while (mask>>=1); | 
 | 109 |  | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 110 | 	return value; | 
 | 111 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 112 | EXPORT_SYMBOL_GPL(ir_extract_bits); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 113 |  | 
 | 114 | static int inline getbit(u32 *samples, int bit) | 
 | 115 | { | 
 | 116 | 	return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; | 
 | 117 | } | 
 | 118 |  | 
 | 119 | /* sump raw samples for visual debugging ;) */ | 
 | 120 | int ir_dump_samples(u32 *samples, int count) | 
 | 121 | { | 
 | 122 | 	int i, bit, start; | 
 | 123 |  | 
 | 124 | 	printk(KERN_DEBUG "ir samples: "); | 
 | 125 | 	start = 0; | 
 | 126 | 	for (i = 0; i < count * 32; i++) { | 
 | 127 | 		bit = getbit(samples,i); | 
 | 128 | 		if (bit) | 
 | 129 | 			start = 1; | 
 | 130 | 		if (0 == start) | 
 | 131 | 			continue; | 
 | 132 | 		printk("%s", bit ? "#" : "_"); | 
 | 133 | 	} | 
 | 134 | 	printk("\n"); | 
 | 135 | 	return 0; | 
 | 136 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 137 | EXPORT_SYMBOL_GPL(ir_dump_samples); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 138 |  | 
 | 139 | /* decode raw samples, pulse distance coding used by NEC remotes */ | 
 | 140 | int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) | 
 | 141 | { | 
 | 142 | 	int i,last,bit,len; | 
 | 143 | 	u32 curBit; | 
 | 144 | 	u32 value; | 
 | 145 |  | 
 | 146 | 	/* find start burst */ | 
 | 147 | 	for (i = len = 0; i < count * 32; i++) { | 
 | 148 | 		bit = getbit(samples,i); | 
 | 149 | 		if (bit) { | 
 | 150 | 			len++; | 
 | 151 | 		} else { | 
 | 152 | 			if (len >= 29) | 
 | 153 | 				break; | 
 | 154 | 			len = 0; | 
 | 155 | 		} | 
 | 156 | 	} | 
 | 157 |  | 
 | 158 | 	/* start burst to short */ | 
 | 159 | 	if (len < 29) | 
 | 160 | 		return 0xffffffff; | 
 | 161 |  | 
 | 162 | 	/* find start silence */ | 
 | 163 | 	for (len = 0; i < count * 32; i++) { | 
 | 164 | 		bit = getbit(samples,i); | 
 | 165 | 		if (bit) { | 
 | 166 | 			break; | 
 | 167 | 		} else { | 
 | 168 | 			len++; | 
 | 169 | 		} | 
 | 170 | 	} | 
 | 171 |  | 
 | 172 | 	/* silence to short */ | 
 | 173 | 	if (len < 7) | 
 | 174 | 		return 0xffffffff; | 
 | 175 |  | 
 | 176 | 	/* go decoding */ | 
 | 177 | 	len   = 0; | 
 | 178 | 	last = 1; | 
 | 179 | 	value = 0; curBit = 1; | 
 | 180 | 	for (; i < count * 32; i++) { | 
 | 181 | 		bit  = getbit(samples,i); | 
 | 182 | 		if (last) { | 
 | 183 | 			if(bit) { | 
 | 184 | 				continue; | 
 | 185 | 			} else { | 
 | 186 | 				len = 1; | 
 | 187 | 			} | 
 | 188 | 		} else { | 
 | 189 | 			if (bit) { | 
 | 190 | 				if (len > (low + high) /2) | 
 | 191 | 					value |= curBit; | 
 | 192 | 				curBit <<= 1; | 
 | 193 | 				if (curBit == 1) | 
 | 194 | 					break; | 
 | 195 | 			} else { | 
 | 196 | 				len++; | 
 | 197 | 			} | 
 | 198 | 		} | 
 | 199 | 		last = bit; | 
 | 200 | 	} | 
 | 201 |  | 
 | 202 | 	return value; | 
 | 203 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 204 | EXPORT_SYMBOL_GPL(ir_decode_pulsedistance); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 205 |  | 
 | 206 | /* decode raw samples, biphase coding, used by rc5 for example */ | 
 | 207 | int ir_decode_biphase(u32 *samples, int count, int low, int high) | 
 | 208 | { | 
 | 209 | 	int i,last,bit,len,flips; | 
 | 210 | 	u32 value; | 
 | 211 |  | 
 | 212 | 	/* find start bit (1) */ | 
 | 213 | 	for (i = 0; i < 32; i++) { | 
 | 214 | 		bit = getbit(samples,i); | 
 | 215 | 		if (bit) | 
 | 216 | 			break; | 
 | 217 | 	} | 
 | 218 |  | 
 | 219 | 	/* go decoding */ | 
 | 220 | 	len   = 0; | 
 | 221 | 	flips = 0; | 
 | 222 | 	value = 1; | 
 | 223 | 	for (; i < count * 32; i++) { | 
 | 224 | 		if (len > high) | 
 | 225 | 			break; | 
 | 226 | 		if (flips > 1) | 
 | 227 | 			break; | 
 | 228 | 		last = bit; | 
 | 229 | 		bit  = getbit(samples,i); | 
 | 230 | 		if (last == bit) { | 
 | 231 | 			len++; | 
 | 232 | 			continue; | 
 | 233 | 		} | 
 | 234 | 		if (len < low) { | 
 | 235 | 			len++; | 
 | 236 | 			flips++; | 
 | 237 | 			continue; | 
 | 238 | 		} | 
 | 239 | 		value <<= 1; | 
 | 240 | 		value |= bit; | 
 | 241 | 		flips = 0; | 
 | 242 | 		len   = 1; | 
 | 243 | 	} | 
 | 244 | 	return value; | 
 | 245 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 246 | EXPORT_SYMBOL_GPL(ir_decode_biphase); | 
| Ricardo Cerqueira | d15549a | 2006-03-03 12:13:42 -0300 | [diff] [blame] | 247 |  | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 248 | /* RC5 decoding stuff, moved from bttv-input.c to share it with | 
 | 249 |  * saa7134 */ | 
 | 250 |  | 
 | 251 | /* decode raw bit pattern to RC5 code */ | 
| Andy Walls | 1d23a00 | 2009-09-27 20:05:23 -0300 | [diff] [blame] | 252 | u32 ir_rc5_decode(unsigned int code) | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 253 | { | 
 | 254 | 	unsigned int org_code = code; | 
 | 255 | 	unsigned int pair; | 
 | 256 | 	unsigned int rc5 = 0; | 
 | 257 | 	int i; | 
 | 258 |  | 
 | 259 | 	for (i = 0; i < 14; ++i) { | 
 | 260 | 		pair = code & 0x3; | 
 | 261 | 		code >>= 2; | 
 | 262 |  | 
 | 263 | 		rc5 <<= 1; | 
 | 264 | 		switch (pair) { | 
 | 265 | 		case 0: | 
 | 266 | 		case 2: | 
 | 267 | 			break; | 
 | 268 | 		case 1: | 
 | 269 | 			rc5 |= 1; | 
 | 270 | 			break; | 
 | 271 | 		case 3: | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 272 | 			IR_dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 273 | 			return 0; | 
 | 274 | 		} | 
 | 275 | 	} | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 276 | 	IR_dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 277 | 		"instr=%x\n", rc5, org_code, RC5_START(rc5), | 
 | 278 | 		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | 
 | 279 | 	return rc5; | 
 | 280 | } | 
| Andy Walls | 1d23a00 | 2009-09-27 20:05:23 -0300 | [diff] [blame] | 281 | EXPORT_SYMBOL_GPL(ir_rc5_decode); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 282 |  | 
 | 283 | void ir_rc5_timer_end(unsigned long data) | 
 | 284 | { | 
 | 285 | 	struct card_ir *ir = (struct card_ir *)data; | 
 | 286 | 	struct timeval tv; | 
 | 287 | 	unsigned long current_jiffies, timeout; | 
 | 288 | 	u32 gap; | 
 | 289 | 	u32 rc5 = 0; | 
 | 290 |  | 
 | 291 | 	/* get time */ | 
 | 292 | 	current_jiffies = jiffies; | 
 | 293 | 	do_gettimeofday(&tv); | 
 | 294 |  | 
 | 295 | 	/* avoid overflow with gap >1s */ | 
 | 296 | 	if (tv.tv_sec - ir->base_time.tv_sec > 1) { | 
 | 297 | 		gap = 200000; | 
 | 298 | 	} else { | 
 | 299 | 		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | 
 | 300 | 		    tv.tv_usec - ir->base_time.tv_usec; | 
 | 301 | 	} | 
 | 302 |  | 
| Vincent Penne | 726cf56 | 2007-03-25 11:58:23 -0300 | [diff] [blame] | 303 | 	/* signal we're ready to start a new code */ | 
 | 304 | 	ir->active = 0; | 
 | 305 |  | 
 | 306 | 	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */ | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 307 | 	if (gap < 28000) { | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 308 | 		IR_dprintk(1, "ir-common: spurious timer_end\n"); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 309 | 		return; | 
 | 310 | 	} | 
 | 311 |  | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 312 | 	if (ir->last_bit < 20) { | 
 | 313 | 		/* ignore spurious codes (caused by light/other remotes) */ | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 314 | 		IR_dprintk(1, "ir-common: short code: %x\n", ir->code); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 315 | 	} else { | 
 | 316 | 		ir->code = (ir->code << ir->shift_by) | 1; | 
 | 317 | 		rc5 = ir_rc5_decode(ir->code); | 
 | 318 |  | 
 | 319 | 		/* two start bits? */ | 
 | 320 | 		if (RC5_START(rc5) != ir->start) { | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 321 | 			IR_dprintk(1, "ir-common: rc5 start bits invalid: %u\n", RC5_START(rc5)); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 322 |  | 
 | 323 | 			/* right address? */ | 
 | 324 | 		} else if (RC5_ADDR(rc5) == ir->addr) { | 
 | 325 | 			u32 toggle = RC5_TOGGLE(rc5); | 
 | 326 | 			u32 instr = RC5_INSTR(rc5); | 
 | 327 |  | 
 | 328 | 			/* Good code, decide if repeat/repress */ | 
 | 329 | 			if (toggle != RC5_TOGGLE(ir->last_rc5) || | 
 | 330 | 			    instr != RC5_INSTR(ir->last_rc5)) { | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 331 | 				IR_dprintk(1, "ir-common: instruction %x, toggle %x\n", instr, | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 332 | 					toggle); | 
 | 333 | 				ir_input_nokey(ir->dev, &ir->ir); | 
| Mauro Carvalho Chehab | 8573b74 | 2009-11-27 22:40:22 -0300 | [diff] [blame] | 334 | 				ir_input_keydown(ir->dev, &ir->ir, instr); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 335 | 			} | 
 | 336 |  | 
 | 337 | 			/* Set/reset key-up timer */ | 
| Mauro Carvalho Chehab | f7518bd | 2007-07-17 16:27:30 -0300 | [diff] [blame] | 338 | 			timeout = current_jiffies + | 
 | 339 | 				  msecs_to_jiffies(ir->rc5_key_timeout); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 340 | 			mod_timer(&ir->timer_keyup, timeout); | 
 | 341 |  | 
 | 342 | 			/* Save code for repeat test */ | 
 | 343 | 			ir->last_rc5 = rc5; | 
 | 344 | 		} | 
 | 345 | 	} | 
 | 346 | } | 
| Mauro Carvalho Chehab | 4db16db | 2008-07-17 22:28:56 -0300 | [diff] [blame] | 347 | EXPORT_SYMBOL_GPL(ir_rc5_timer_end); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 348 |  | 
 | 349 | void ir_rc5_timer_keyup(unsigned long data) | 
 | 350 | { | 
 | 351 | 	struct card_ir *ir = (struct card_ir *)data; | 
 | 352 |  | 
| Mauro Carvalho Chehab | 4e89217 | 2009-11-27 21:54:41 -0300 | [diff] [blame] | 353 | 	IR_dprintk(1, "ir-common: key released\n"); | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 354 | 	ir_input_nokey(ir->dev, &ir->ir); | 
 | 355 | } | 
| Hermann Pitton | 9160723 | 2006-12-07 21:45:28 -0300 | [diff] [blame] | 356 | EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); |