1 #include <linux/types.h>
2 #include <linux/init.h>
3 #include <linux/module.h>
4 #include <linux/moduleparam.h>
5 #include <linux/input.h>
6 #include <linux/proc_fs.h>
7 #include <asm/bitops.h>
11 #define UP_TIMEOUT (HZ/4)
13 /* enable ir debugging by or'ing debug with 16 */
15 static int ir_initialized
;
16 static struct input_dev input_dev
;
20 static u16 key_map
[256] = {
21 KEY_0
, KEY_1
, KEY_2
, KEY_3
, KEY_4
, KEY_5
, KEY_6
, KEY_7
,
22 KEY_8
, KEY_9
, KEY_BACK
, 0, KEY_POWER
, KEY_MUTE
, 0, KEY_INFO
,
23 KEY_VOLUMEUP
, KEY_VOLUMEDOWN
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 KEY_CHANNELUP
, KEY_CHANNELDOWN
, 0, 0, 0, 0, 0, 0,
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26 0, 0, 0, 0, KEY_TEXT
, 0, 0, KEY_TV
, 0, 0, 0, 0, 0, KEY_SETUP
, 0, 0,
27 0, 0, 0, KEY_SUBTITLE
, 0, 0, KEY_LANGUAGE
, 0,
28 KEY_RADIO
, 0, 0, 0, 0, KEY_EXIT
, 0, 0,
29 KEY_UP
, KEY_DOWN
, KEY_LEFT
, KEY_RIGHT
, KEY_OK
, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RED
, KEY_GREEN
, KEY_YELLOW
,
31 KEY_BLUE
, 0, 0, 0, 0, 0, 0, 0, KEY_MENU
, KEY_LIST
, 0, 0, 0, 0, 0, 0,
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, KEY_UP
, KEY_UP
, KEY_DOWN
, KEY_DOWN
,
37 0, 0, 0, 0, KEY_EPG
, 0, 0, 0,
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_VCR
44 static void av7110_emit_keyup(unsigned long data
)
46 if (!data
|| !test_bit(data
, input_dev
.key
))
49 input_event(&input_dev
, EV_KEY
, data
, !!0);
53 static struct timer_list keyup_timer
= { .function
= av7110_emit_keyup
};
56 static void av7110_emit_key(u32 ircom
)
60 static u16 old_toggle
= 0;
64 /* extract device address and data */
65 if (ir_config
& 0x0001) {
66 /* TODO RCMM: ? bits device address, 8 bits data */
68 addr
= (ircom
>> 8) & 0xff;
70 /* RC5: 5 bits device address, 6 bits data */
72 addr
= (ircom
>> 6) & 0x1f;
75 keycode
= key_map
[data
];
77 dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
78 ircom
, addr
, data
, keycode
);
80 /* check device address (if selected) */
81 if (ir_config
& 0x4000)
82 if (addr
!= ((ir_config
>> 16) & 0xff))
86 printk ("%s: unknown key 0x%02x!!\n", __FUNCTION__
, data
);
90 if (ir_config
& 0x0001)
91 new_toggle
= 0; /* RCMM */
93 new_toggle
= (ircom
& 0x800); /* RC5 */
95 if (timer_pending(&keyup_timer
)) {
96 del_timer(&keyup_timer
);
97 if (keyup_timer
.data
!= keycode
|| new_toggle
!= old_toggle
) {
98 input_event(&input_dev
, EV_KEY
, keyup_timer
.data
, !!0);
99 input_event(&input_dev
, EV_KEY
, keycode
, !0);
101 input_event(&input_dev
, EV_KEY
, keycode
, 2);
104 input_event(&input_dev
, EV_KEY
, keycode
, !0);
106 keyup_timer
.expires
= jiffies
+ UP_TIMEOUT
;
107 keyup_timer
.data
= keycode
;
109 add_timer(&keyup_timer
);
111 old_toggle
= new_toggle
;
114 static void input_register_keys(void)
118 memset(input_dev
.keybit
, 0, sizeof(input_dev
.keybit
));
120 for (i
= 0; i
< sizeof(key_map
) / sizeof(key_map
[0]); i
++) {
121 if (key_map
[i
] > KEY_MAX
)
123 else if (key_map
[i
] > KEY_RESERVED
)
124 set_bit(key_map
[i
], input_dev
.keybit
);
129 static void input_repeat_key(unsigned long data
)
131 /* dummy routine to disable autorepeat in the input driver */
135 static int av7110_ir_write_proc(struct file
*file
, const char __user
*buffer
,
136 unsigned long count
, void *data
)
139 int size
= 4 + 256 * sizeof(u16
);
144 page
= (char *) vmalloc(size
);
148 if (copy_from_user(page
, buffer
, size
)) {
153 memcpy(&ir_config
, page
, 4);
154 memcpy(&key_map
, page
+ 4, 256 * sizeof(u16
));
156 av7110_setup_irc_config(NULL
, ir_config
);
157 input_register_keys();
162 int __init
av7110_ir_init(void)
164 static struct proc_dir_entry
*e
;
169 init_timer(&keyup_timer
);
170 keyup_timer
.data
= 0;
172 input_dev
.name
= "DVB on-card IR receiver";
177 set_bit(EV_KEY
, input_dev
.evbit
);
178 set_bit(EV_REP
, input_dev
.evbit
);
180 input_register_keys();
182 input_register_device(&input_dev
);
183 input_dev
.timer
.function
= input_repeat_key
;
185 av7110_setup_irc_config(NULL
, 0x0001);
186 av7110_register_irc_handler(av7110_emit_key
);
188 e
= create_proc_entry("av7110_ir", S_IFREG
| S_IRUGO
| S_IWUSR
, NULL
);
190 e
->write_proc
= av7110_ir_write_proc
;
191 e
->size
= 4 + 256 * sizeof(u16
);
199 void __exit
av7110_ir_exit(void)
201 if (ir_initialized
== 0)
203 del_timer_sync(&keyup_timer
);
204 remove_proc_entry("av7110_ir", NULL
);
205 av7110_unregister_irc_handler(av7110_emit_key
);
206 input_unregister_device(&input_dev
);
210 //MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
211 //MODULE_LICENSE("GPL");