2 * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices
3 * based on reference design made by DiBcom (http://www.dibcom.fr/)
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
7 * see dvb-dibusb-core.c for more copyright details.
9 * This file contains functions for handling the event device on the software
10 * side and the remote control on the hardware side.
12 #include "dvb-dibusb.h"
14 /* Table to map raw key codes to key events. This should not be hard-wired
16 static const struct { u8 c0
, c1
, c2
; uint32_t key
; } nec_rc_keys
[] =
18 /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
19 { 0x00, 0xff, 0x16, KEY_POWER
},
20 { 0x00, 0xff, 0x10, KEY_MUTE
},
21 { 0x00, 0xff, 0x03, KEY_1
},
22 { 0x00, 0xff, 0x01, KEY_2
},
23 { 0x00, 0xff, 0x06, KEY_3
},
24 { 0x00, 0xff, 0x09, KEY_4
},
25 { 0x00, 0xff, 0x1d, KEY_5
},
26 { 0x00, 0xff, 0x1f, KEY_6
},
27 { 0x00, 0xff, 0x0d, KEY_7
},
28 { 0x00, 0xff, 0x19, KEY_8
},
29 { 0x00, 0xff, 0x1b, KEY_9
},
30 { 0x00, 0xff, 0x15, KEY_0
},
31 { 0x00, 0xff, 0x05, KEY_CHANNELUP
},
32 { 0x00, 0xff, 0x02, KEY_CHANNELDOWN
},
33 { 0x00, 0xff, 0x1e, KEY_VOLUMEUP
},
34 { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN
},
35 { 0x00, 0xff, 0x11, KEY_RECORD
},
36 { 0x00, 0xff, 0x17, KEY_FAVORITES
}, /* Heart symbol - Channel list. */
37 { 0x00, 0xff, 0x14, KEY_PLAY
},
38 { 0x00, 0xff, 0x1a, KEY_STOP
},
39 { 0x00, 0xff, 0x40, KEY_REWIND
},
40 { 0x00, 0xff, 0x12, KEY_FASTFORWARD
},
41 { 0x00, 0xff, 0x0e, KEY_PREVIOUS
}, /* Recall - Previous channel. */
42 { 0x00, 0xff, 0x4c, KEY_PAUSE
},
43 { 0x00, 0xff, 0x4d, KEY_SCREEN
}, /* Full screen mode. */
44 { 0x00, 0xff, 0x54, KEY_AUDIO
}, /* MTS - Switch to secondary audio. */
45 /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
46 { 0x00, 0xff, 0x0c, KEY_CANCEL
}, /* Cancel */
47 { 0x00, 0xff, 0x1c, KEY_EPG
}, /* EPG */
48 { 0x00, 0xff, 0x00, KEY_TAB
}, /* Tab */
49 { 0x00, 0xff, 0x48, KEY_INFO
}, /* Preview */
50 { 0x00, 0xff, 0x04, KEY_LIST
}, /* RecordList */
51 { 0x00, 0xff, 0x0f, KEY_TEXT
}, /* Teletext */
52 /* Key codes for the KWorld/ADSTech/JetWay remote. */
53 { 0x86, 0x6b, 0x12, KEY_POWER
},
54 { 0x86, 0x6b, 0x0f, KEY_SELECT
}, /* source */
55 { 0x86, 0x6b, 0x0c, KEY_UNKNOWN
}, /* scan */
56 { 0x86, 0x6b, 0x0b, KEY_EPG
},
57 { 0x86, 0x6b, 0x10, KEY_MUTE
},
58 { 0x86, 0x6b, 0x01, KEY_1
},
59 { 0x86, 0x6b, 0x02, KEY_2
},
60 { 0x86, 0x6b, 0x03, KEY_3
},
61 { 0x86, 0x6b, 0x04, KEY_4
},
62 { 0x86, 0x6b, 0x05, KEY_5
},
63 { 0x86, 0x6b, 0x06, KEY_6
},
64 { 0x86, 0x6b, 0x07, KEY_7
},
65 { 0x86, 0x6b, 0x08, KEY_8
},
66 { 0x86, 0x6b, 0x09, KEY_9
},
67 { 0x86, 0x6b, 0x0a, KEY_0
},
68 { 0x86, 0x6b, 0x18, KEY_ZOOM
},
69 { 0x86, 0x6b, 0x1c, KEY_UNKNOWN
}, /* preview */
70 { 0x86, 0x6b, 0x13, KEY_UNKNOWN
}, /* snap */
71 { 0x86, 0x6b, 0x00, KEY_UNDO
},
72 { 0x86, 0x6b, 0x1d, KEY_RECORD
},
73 { 0x86, 0x6b, 0x0d, KEY_STOP
},
74 { 0x86, 0x6b, 0x0e, KEY_PAUSE
},
75 { 0x86, 0x6b, 0x16, KEY_PLAY
},
76 { 0x86, 0x6b, 0x11, KEY_BACK
},
77 { 0x86, 0x6b, 0x19, KEY_FORWARD
},
78 { 0x86, 0x6b, 0x14, KEY_UNKNOWN
}, /* pip */
79 { 0x86, 0x6b, 0x15, KEY_ESC
},
80 { 0x86, 0x6b, 0x1a, KEY_UP
},
81 { 0x86, 0x6b, 0x1e, KEY_DOWN
},
82 { 0x86, 0x6b, 0x1f, KEY_LEFT
},
83 { 0x86, 0x6b, 0x1b, KEY_RIGHT
},
86 /* Hauppauge NOVA-T USB2 keys */
87 static const struct { u16 raw
; uint32_t key
; } haupp_rc_keys
[] = {
103 { 0xc87, KEY_VOLUMEUP
},
104 { 0xc8f, KEY_VOLUMEDOWN
},
105 { 0xc97, KEY_CHANNEL
},
107 { 0xd07, KEY_CHANNELUP
},
108 { 0xd0f, KEY_CHANNELDOWN
},
109 { 0xdbf, KEY_RECORD
},
111 { 0xd97, KEY_REWIND
},
113 { 0xda7, KEY_FASTFORWARD
},
114 { 0xd27, KEY_LAST
}, /* Skip backwards */
115 { 0xd87, KEY_PAUSE
},
127 { 0xc57, KEY_KPASTERISK
},
128 { 0xc77, KEY_GRAVE
}, /* # */
130 { 0xd77, KEY_GREEN
},
131 { 0xdc7, KEY_YELLOW
},
135 static int dibusb_key2event_nec(struct usb_dibusb
*dib
,u8 rb
[5])
139 case DIBUSB_RC_NEC_KEY_PRESSED
:
140 /* rb[1-3] is the actual key, rb[4] is a checksum */
141 deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
142 rb
[1], rb
[2], rb
[3], rb
[4]);
144 if ((0xff - rb
[3]) != rb
[4]) {
145 deb_rc("remote control checksum failed.\n");
149 /* See if we can match the raw key code. */
150 for (i
= 0; i
< sizeof(nec_rc_keys
)/sizeof(nec_rc_keys
[0]); i
++) {
151 if (nec_rc_keys
[i
].c0
== rb
[1] &&
152 nec_rc_keys
[i
].c1
== rb
[2] &&
153 nec_rc_keys
[i
].c2
== rb
[3]) {
155 dib
->last_event
= nec_rc_keys
[i
].key
;
160 case DIBUSB_RC_NEC_KEY_REPEATED
:
161 /* rb[1]..rb[4] are always zero.*/
162 /* Repeats often seem to occur so for the moment just ignore this. */
164 case DIBUSB_RC_NEC_EMPTY
: /* No (more) remote control keys. */
171 static int dibusb_key2event_hauppauge(struct usb_dibusb
*dib
,u8 rb
[4])
176 case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED
:
177 raw
= ((rb
[1] & 0x0f) << 8) | rb
[2];
179 state
= !!(rb
[1] & 0x40);
181 deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb
[1],rb
[2],rb
[3],raw
,state
);
182 for (i
= 0; i
< sizeof(haupp_rc_keys
)/sizeof(haupp_rc_keys
[0]); i
++) {
183 if (haupp_rc_keys
[i
].raw
== raw
) {
184 if (dib
->last_event
== haupp_rc_keys
[i
].key
&&
185 dib
->last_state
== state
) {
186 deb_rc("key repeat\n");
189 dib
->last_event
= haupp_rc_keys
[i
].key
;
190 dib
->last_state
= state
;
197 case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY
:
205 * Read the remote control and feed the appropriate event.
206 * NEC protocol is used for remote controls
208 static int dibusb_read_remote_control(struct usb_dibusb
*dib
)
210 u8 b
[1] = { DIBUSB_REQ_POLL_REMOTE
}, rb
[5];
213 if ((ret
= dibusb_readwrite_usb(dib
,b
,1,rb
,5)))
216 switch (dib
->dibdev
->dev_cl
->remote_type
) {
217 case DIBUSB_RC_NEC_PROTOCOL
:
218 event
= dibusb_key2event_nec(dib
,rb
);
220 case DIBUSB_RC_HAUPPAUGE_PROTO
:
221 event
= dibusb_key2event_hauppauge(dib
,rb
);
228 if (++dib
->repeat_key_count
< dib
->rc_key_repeat_count
) {
229 deb_rc("key repeat dropped. (%d)\n",dib
->repeat_key_count
);
230 event
= -1; /* skip this key repeat */
233 if (event
== 1 || event
== 0) {
234 deb_rc("Translated key 0x%04x\n",event
);
236 /* Signal down and up events for this key. */
237 input_report_key(&dib
->rc_input_dev
, dib
->last_event
, 1);
238 input_report_key(&dib
->rc_input_dev
, dib
->last_event
, 0);
239 input_sync(&dib
->rc_input_dev
);
242 dib
->repeat_key_count
= 0;
247 /* Remote-control poll function - called every dib->rc_query_interval ms to see
248 whether the remote control has received anything. */
249 static void dibusb_remote_query(void *data
)
251 struct usb_dibusb
*dib
= (struct usb_dibusb
*) data
;
252 /* TODO: need a lock here. We can simply skip checking for the remote control
254 dibusb_read_remote_control(dib
);
255 schedule_delayed_work(&dib
->rc_query_work
,
256 msecs_to_jiffies(dib
->rc_query_interval
));
259 int dibusb_remote_init(struct usb_dibusb
*dib
)
263 if (dib
->dibdev
->dev_cl
->remote_type
== DIBUSB_RC_NO
)
266 /* Initialise the remote-control structures.*/
267 init_input_dev(&dib
->rc_input_dev
);
269 dib
->rc_input_dev
.evbit
[0] = BIT(EV_KEY
);
270 dib
->rc_input_dev
.keycodesize
= sizeof(unsigned char);
271 dib
->rc_input_dev
.keycodemax
= KEY_MAX
;
272 dib
->rc_input_dev
.name
= DRIVER_DESC
" remote control";
274 switch (dib
->dibdev
->dev_cl
->remote_type
) {
275 case DIBUSB_RC_NEC_PROTOCOL
:
276 for (i
=0; i
<sizeof(nec_rc_keys
)/sizeof(nec_rc_keys
[0]); i
++)
277 set_bit(nec_rc_keys
[i
].key
, dib
->rc_input_dev
.keybit
);
279 case DIBUSB_RC_HAUPPAUGE_PROTO
:
280 for (i
=0; i
<sizeof(haupp_rc_keys
)/sizeof(haupp_rc_keys
[0]); i
++)
281 set_bit(haupp_rc_keys
[i
].key
, dib
->rc_input_dev
.keybit
);
288 input_register_device(&dib
->rc_input_dev
);
290 INIT_WORK(&dib
->rc_query_work
, dibusb_remote_query
, dib
);
292 /* Start the remote-control polling. */
293 if (dib
->rc_query_interval
< 40)
294 dib
->rc_query_interval
= 100; /* default */
296 info("schedule remote query interval to %d msecs.",dib
->rc_query_interval
);
297 schedule_delayed_work(&dib
->rc_query_work
,msecs_to_jiffies(dib
->rc_query_interval
));
299 dib
->init_state
|= DIBUSB_STATE_REMOTE
;
304 int dibusb_remote_exit(struct usb_dibusb
*dib
)
306 if (dib
->dibdev
->dev_cl
->remote_type
== DIBUSB_RC_NO
)
309 if (dib
->init_state
& DIBUSB_STATE_REMOTE
) {
310 cancel_delayed_work(&dib
->rc_query_work
);
311 flush_scheduled_work();
312 input_unregister_device(&dib
->rc_input_dev
);
314 dib
->init_state
&= ~DIBUSB_STATE_REMOTE
;