2005-06-24 09:02:35 +04:00
/* dvb-usb-remote.c is part of the DVB USB library.
*
* Copyright ( C ) 2004 - 5 Patrick Boettcher ( patrick . boettcher @ desy . de )
* see dvb - usb - init . c for copyright information .
*
* This file contains functions for initializing the the input - device and for handling remote - control - queries .
*/
# include "dvb-usb-common.h"
2006-08-28 06:01:24 +04:00
# include <linux/usb/input.h>
2005-06-24 09:02:35 +04:00
/* Remote-control poll function - called every dib->rc_query_interval ms to see
* whether the remote control has received anything .
*
* TODO : Fix the repeat rate of the input device .
*/
static void dvb_usb_read_remote_control ( void * data )
{
struct dvb_usb_device * d = data ;
u32 event ;
int state ;
/* TODO: need a lock here. We can simply skip checking for the remote control
if we ' re busy . */
2005-07-08 04:58:11 +04:00
/* when the parameter has been set to 1 via sysfs while the driver was running */
if ( dvb_usb_disable_rc_polling )
return ;
2005-06-24 09:02:35 +04:00
if ( d - > props . rc_query ( d , & event , & state ) ) {
err ( " error while querying for an remote control event. " ) ;
goto schedule ;
}
switch ( state ) {
case REMOTE_NO_KEY_PRESSED :
break ;
case REMOTE_KEY_PRESSED :
deb_rc ( " key pressed \n " ) ;
d - > last_event = event ;
case REMOTE_KEY_REPEAT :
deb_rc ( " key repeated \n " ) ;
2005-09-15 11:01:53 +04:00
input_event ( d - > rc_input_dev , EV_KEY , event , 1 ) ;
input_event ( d - > rc_input_dev , EV_KEY , d - > last_event , 0 ) ;
input_sync ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
break ;
default :
break ;
}
/* improved repeat handling ???
switch ( state ) {
case REMOTE_NO_KEY_PRESSED :
deb_rc ( " NO KEY PRESSED \n " ) ;
if ( d - > last_state ! = REMOTE_NO_KEY_PRESSED ) {
deb_rc ( " releasing event %d \n " , d - > last_event ) ;
2005-09-15 11:01:53 +04:00
input_event ( d - > rc_input_dev , EV_KEY , d - > last_event , 0 ) ;
input_sync ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
}
d - > last_state = REMOTE_NO_KEY_PRESSED ;
d - > last_event = 0 ;
break ;
case REMOTE_KEY_PRESSED :
deb_rc ( " KEY PRESSED \n " ) ;
deb_rc ( " pressing event %d \n " , event ) ;
2005-09-15 11:01:53 +04:00
input_event ( d - > rc_input_dev , EV_KEY , event , 1 ) ;
input_sync ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
d - > last_event = event ;
d - > last_state = REMOTE_KEY_PRESSED ;
break ;
case REMOTE_KEY_REPEAT :
deb_rc ( " KEY_REPEAT \n " ) ;
if ( d - > last_state ! = REMOTE_NO_KEY_PRESSED ) {
deb_rc ( " repeating event %d \n " , d - > last_event ) ;
2005-09-15 11:01:53 +04:00
input_event ( d - > rc_input_dev , EV_KEY , d - > last_event , 2 ) ;
input_sync ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
d - > last_state = REMOTE_KEY_REPEAT ;
}
default :
break ;
}
*/
schedule :
schedule_delayed_work ( & d - > rc_query_work , msecs_to_jiffies ( d - > props . rc_interval ) ) ;
}
int dvb_usb_remote_init ( struct dvb_usb_device * d )
{
int i ;
2005-09-15 11:01:53 +04:00
2005-07-08 04:58:11 +04:00
if ( d - > props . rc_key_map = = NULL | |
d - > props . rc_query = = NULL | |
dvb_usb_disable_rc_polling )
2005-06-24 09:02:35 +04:00
return 0 ;
2005-09-15 11:01:53 +04:00
usb_make_path ( d - > udev , d - > rc_phys , sizeof ( d - > rc_phys ) ) ;
2006-08-28 06:01:24 +04:00
strlcat ( d - > rc_phys , " /ir0 " , sizeof ( d - > rc_phys ) ) ;
2005-09-15 11:01:53 +04:00
d - > rc_input_dev = input_allocate_device ( ) ;
if ( ! d - > rc_input_dev )
return - ENOMEM ;
2005-06-24 09:02:35 +04:00
2005-09-15 11:01:53 +04:00
d - > rc_input_dev - > evbit [ 0 ] = BIT ( EV_KEY ) ;
d - > rc_input_dev - > keycodesize = sizeof ( unsigned char ) ;
d - > rc_input_dev - > keycodemax = KEY_MAX ;
d - > rc_input_dev - > name = " IR-receiver inside an USB DVB receiver " ;
d - > rc_input_dev - > phys = d - > rc_phys ;
2006-08-28 06:01:24 +04:00
usb_to_input_id ( d - > udev , & d - > rc_input_dev - > id ) ;
d - > rc_input_dev - > cdev . dev = & d - > udev - > dev ;
2005-06-24 09:02:35 +04:00
/* set the bits for the keys */
2005-09-15 11:01:53 +04:00
deb_rc ( " key map size: %d \n " , d - > props . rc_key_map_size ) ;
2005-06-24 09:02:35 +04:00
for ( i = 0 ; i < d - > props . rc_key_map_size ; i + + ) {
deb_rc ( " setting bit for event %d item %d \n " , d - > props . rc_key_map [ i ] . event , i ) ;
2005-09-15 11:01:53 +04:00
set_bit ( d - > props . rc_key_map [ i ] . event , d - > rc_input_dev - > keybit ) ;
2005-06-24 09:02:35 +04:00
}
/* Start the remote-control polling. */
if ( d - > props . rc_interval < 40 )
d - > props . rc_interval = 100 ; /* default */
/* setting these two values to non-zero, we have to manage key repeats */
2005-09-15 11:01:53 +04:00
d - > rc_input_dev - > rep [ REP_PERIOD ] = d - > props . rc_interval ;
d - > rc_input_dev - > rep [ REP_DELAY ] = d - > props . rc_interval + 150 ;
2005-06-24 09:02:35 +04:00
2005-09-15 11:01:53 +04:00
input_register_device ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
INIT_WORK ( & d - > rc_query_work , dvb_usb_read_remote_control , d ) ;
2005-09-15 11:01:53 +04:00
info ( " schedule remote query interval to %d msecs. " , d - > props . rc_interval ) ;
2005-06-24 09:02:35 +04:00
schedule_delayed_work ( & d - > rc_query_work , msecs_to_jiffies ( d - > props . rc_interval ) ) ;
d - > state | = DVB_USB_STATE_REMOTE ;
return 0 ;
}
int dvb_usb_remote_exit ( struct dvb_usb_device * d )
{
if ( d - > state & DVB_USB_STATE_REMOTE ) {
cancel_delayed_work ( & d - > rc_query_work ) ;
flush_scheduled_work ( ) ;
2005-09-15 11:01:53 +04:00
input_unregister_device ( d - > rc_input_dev ) ;
2005-06-24 09:02:35 +04:00
}
d - > state & = ~ DVB_USB_STATE_REMOTE ;
return 0 ;
}
# define DVB_USB_RC_NEC_EMPTY 0x00
# define DVB_USB_RC_NEC_KEY_PRESSED 0x01
# define DVB_USB_RC_NEC_KEY_REPEATED 0x02
int dvb_usb_nec_rc_key_to_event ( struct dvb_usb_device * d ,
u8 keybuf [ 5 ] , u32 * event , int * state )
{
int i ;
struct dvb_usb_rc_key * keymap = d - > props . rc_key_map ;
* event = 0 ;
* state = REMOTE_NO_KEY_PRESSED ;
switch ( keybuf [ 0 ] ) {
case DVB_USB_RC_NEC_EMPTY :
break ;
case DVB_USB_RC_NEC_KEY_PRESSED :
if ( ( u8 ) ~ keybuf [ 1 ] ! = keybuf [ 2 ] | |
( u8 ) ~ keybuf [ 3 ] ! = keybuf [ 4 ] ) {
deb_err ( " remote control checksum failed. \n " ) ;
break ;
}
/* See if we can match the raw key code. */
2005-07-08 04:58:24 +04:00
for ( i = 0 ; i < d - > props . rc_key_map_size ; i + + )
2005-06-24 09:02:35 +04:00
if ( keymap [ i ] . custom = = keybuf [ 1 ] & &
keymap [ i ] . data = = keybuf [ 3 ] ) {
* event = keymap [ i ] . event ;
* state = REMOTE_KEY_PRESSED ;
2005-07-08 04:58:24 +04:00
return 0 ;
2005-06-24 09:02:35 +04:00
}
deb_err ( " key mapping failed - no appropriate key found in keymapping \n " ) ;
break ;
case DVB_USB_RC_NEC_KEY_REPEATED :
* state = REMOTE_KEY_REPEAT ;
break ;
default :
deb_err ( " unkown type of remote status: %d \n " , keybuf [ 0 ] ) ;
break ;
}
return 0 ;
}
EXPORT_SYMBOL ( dvb_usb_nec_rc_key_to_event ) ;