2005-11-08 21:37:32 -08:00
/*
2005-11-08 21:38:25 -08:00
handle em28xx IR remotes via linux kernel input layer .
Copyright ( C ) 2005 Ludovico Cavedon < cavedon @ sssup . it >
Markus Rechberger < mrechberger @ gmail . com >
Mauro Carvalho Chehab < mchehab @ brturbo . com . br >
Sascha Sommer < saschasommer @ freenet . de >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2005-11-08 21:37:32 -08:00
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
# include <linux/input.h>
# include <linux/usb.h>
2005-11-08 21:38:25 -08:00
# include "em28xx.h"
2005-11-08 21:37:32 -08:00
static unsigned int disable_ir = 0 ;
module_param ( disable_ir , int , 0444 ) ;
MODULE_PARM_DESC ( disable_ir , " disable infrared remote support " ) ;
static unsigned int ir_debug = 0 ;
module_param ( ir_debug , int , 0644 ) ;
MODULE_PARM_DESC ( ir_debug , " enable debug messages [IR] " ) ;
# define dprintk(fmt, arg...) if (ir_debug) \
printk ( KERN_DEBUG " %s/ir: " fmt , ir - > c . name , # # arg )
/* ---------------------------------------------------------------------- */
2005-11-08 21:37:35 -08:00
static IR_KEYTAB_TYPE ir_codes_em_terratec [ IR_KEYTAB_SIZE ] = {
2005-11-08 21:37:43 -08:00
[ 0x01 ] = KEY_CHANNEL ,
[ 0x02 ] = KEY_SELECT ,
[ 0x03 ] = KEY_MUTE ,
[ 0x04 ] = KEY_POWER ,
[ 0x05 ] = KEY_KP1 ,
[ 0x06 ] = KEY_KP2 ,
[ 0x07 ] = KEY_KP3 ,
[ 0x08 ] = KEY_CHANNELUP ,
[ 0x09 ] = KEY_KP4 ,
[ 0x0a ] = KEY_KP5 ,
[ 0x0b ] = KEY_KP6 ,
[ 0x0c ] = KEY_CHANNELDOWN ,
[ 0x0d ] = KEY_KP7 ,
[ 0x0e ] = KEY_KP8 ,
[ 0x0f ] = KEY_KP9 ,
[ 0x10 ] = KEY_VOLUMEUP ,
[ 0x11 ] = KEY_KP0 ,
[ 0x12 ] = KEY_MENU ,
[ 0x13 ] = KEY_PRINT ,
[ 0x14 ] = KEY_VOLUMEDOWN ,
[ 0x16 ] = KEY_PAUSE ,
[ 0x18 ] = KEY_RECORD ,
[ 0x19 ] = KEY_REWIND ,
[ 0x1a ] = KEY_PLAY ,
2005-11-08 21:37:35 -08:00
[ 0x1b ] = KEY_FORWARD ,
[ 0x1c ] = KEY_BACKSPACE ,
2005-11-08 21:37:43 -08:00
[ 0x1e ] = KEY_STOP ,
[ 0x40 ] = KEY_ZOOM ,
2005-11-08 21:37:32 -08:00
} ;
/* ----------------------------------------------------------------------- */
2005-11-08 21:37:35 -08:00
static int get_key_terratec ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
unsigned char b ;
/* poll IR chip */
if ( 1 ! = i2c_master_recv ( & ir - > c , & b , 1 ) ) {
dprintk ( " read error \n " ) ;
return - EIO ;
}
/* it seems that 0xFE indicates that a button is still hold
2005-11-08 21:37:36 -08:00
down , while 0xff indicates that no button is hold
down . 0xfe sequences are sometimes interrupted by 0xFF */
2005-11-08 21:37:35 -08:00
dprintk ( " key %02x \n " , b ) ;
2005-11-08 21:37:36 -08:00
if ( b = = 0xff )
2005-11-08 21:37:35 -08:00
return 0 ;
2005-11-08 21:37:36 -08:00
if ( b = = 0xfe )
2005-11-08 21:37:35 -08:00
/* keep old data */
return 1 ;
* ir_key = b ;
* ir_raw = b ;
return 1 ;
}
2005-11-08 21:37:32 -08:00
static int get_key_em_haup ( struct IR_i2c * ir , u32 * ir_key , u32 * ir_raw )
{
unsigned char buf [ 2 ] ;
unsigned char code ;
/* poll IR chip */
if ( 2 ! = i2c_master_recv ( & ir - > c , buf , 2 ) )
return - EIO ;
/* Does eliminate repeated parity code */
if ( buf [ 1 ] = = 0xff )
return 0 ;
ir - > old = buf [ 1 ] ;
/* Rearranges bits to the right order */
code = ( ( buf [ 0 ] & 0x01 ) < < 5 ) | /* 0010 0000 */
( ( buf [ 0 ] & 0x02 ) < < 3 ) | /* 0001 0000 */
( ( buf [ 0 ] & 0x04 ) < < 1 ) | /* 0000 1000 */
( ( buf [ 0 ] & 0x08 ) > > 1 ) | /* 0000 0100 */
( ( buf [ 0 ] & 0x10 ) > > 3 ) | /* 0000 0010 */
( ( buf [ 0 ] & 0x20 ) > > 5 ) ; /* 0000 0001 */
dprintk ( " ir hauppauge (em2840): code=0x%02x (rcv=0x%02x) \n " , code , buf [ 0 ] ) ;
/* return key */
* ir_key = code ;
* ir_raw = code ;
return 1 ;
}
/* ----------------------------------------------------------------------- */
2005-11-08 21:38:27 -08:00
void em28xx_set_ir ( struct em28xx * dev , struct IR_i2c * ir )
2005-11-08 21:37:32 -08:00
{
2005-11-08 21:37:56 -08:00
if ( disable_ir ) {
ir - > get_key = NULL ;
2005-11-08 21:37:32 -08:00
return ;
2005-11-08 21:37:56 -08:00
}
2005-11-08 21:37:32 -08:00
/* detect & configure */
switch ( dev - > model ) {
case ( EM2800_BOARD_UNKNOWN ) :
break ;
case ( EM2820_BOARD_UNKNOWN ) :
break ;
2005-11-08 21:37:37 -08:00
case ( EM2800_BOARD_TERRATEC_CINERGY_200 ) :
2005-11-08 21:37:32 -08:00
case ( EM2820_BOARD_TERRATEC_CINERGY_250 ) :
2005-11-08 21:37:35 -08:00
ir - > ir_codes = ir_codes_em_terratec ;
ir - > get_key = get_key_terratec ;
2005-11-08 21:38:27 -08:00
snprintf ( ir - > c . name , sizeof ( ir - > c . name ) , " i2c IR (EM28XX Terratec) " ) ;
2005-11-08 21:37:32 -08:00
break ;
case ( EM2820_BOARD_PINNACLE_USB_2 ) :
break ;
case ( EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 ) :
ir - > ir_codes = ir_codes_hauppauge_new ;
ir - > get_key = get_key_em_haup ;
2005-11-08 21:37:35 -08:00
snprintf ( ir - > c . name , sizeof ( ir - > c . name ) , " i2c IR (EM2840 Hauppauge) " ) ;
2005-11-08 21:37:32 -08:00
break ;
case ( EM2820_BOARD_MSI_VOX_USB_2 ) :
break ;
case ( EM2800_BOARD_LEADTEK_WINFAST_USBII ) :
break ;
case ( EM2800_BOARD_KWORLD_USB2800 ) :
break ;
}
}
/* ----------------------------------------------------------------------
* Local variables :
* c - basic - offset : 8
* End :
*/