2005-04-17 02:20:36 +04:00
/*
*
* keyboard input driver for i2c IR remote controls
*
* Copyright ( c ) 2000 - 2003 Gerd Knorr < kraxel @ bytesex . org >
* modified for PixelView ( BT878P + W / FM ) by
* Michal Kochanowicz < mkochano @ pld . org . pl >
* Christoph Bartelmus < lirc @ bartelmus . de >
* modified for KNC ONE TV Station / Anubis Typhoon TView Tuner by
* Ulrich Mueller < ulrich . mueller42 @ web . de >
2005-11-09 08:37:21 +03:00
* modified for em2820 based USB TV tuners by
* Markus Rechberger < mrechberger @ gmail . com >
2007-08-24 08:02:32 +04:00
* modified for DViCO Fusion HDTV 5 RT GOLD by
* Chaogui Zhang < czhang1974 @ gmail . com >
2008-10-13 15:37:06 +04:00
* modified for MSI TV @ nywhere Plus by
* Henry Wong < henry @ stuffedcow . net >
* Mark Schultz < n9xmj @ yahoo . com >
* Brian Rogers < brian_rogers @ comcast . net >
2009-02-12 09:43:11 +03:00
* modified for AVerMedia Cardbus by
* Oldrich Jedlicka < oldium . pro @ seznam . cz >
2017-10-21 15:16:47 +03:00
* Zilog Transmitter portions / ideas were derived from GPLv2 + sources :
* - drivers / char / pctv_zilogir . [ ch ] from Hauppauge Broadway product
* Copyright 2011 Hauppauge Computer works
* - drivers / staging / media / lirc / lirc_zilog . c
* Copyright ( c ) 2000 Gerd Knorr < kraxel @ goldbach . in - berlin . de >
* Michal Kochanowicz < mkochano @ pld . org . pl >
* Christoph Bartelmus < lirc @ bartelmus . de >
* Ulrich Mueller < ulrich . mueller42 @ web . de >
* Stefan Jahn < stefan @ lkcc . org >
* Jerome Brock < jbrock @ users . sourceforge . net >
* Thomas Reitmayr ( treitmayr @ yahoo . com )
* Mark Weaver < mark @ npsl . co . uk >
* Jarod Wilson < jarod @ redhat . com >
* Copyright ( C ) 2011 Andy Walls < awalls @ md . metrocast . net >
2005-04-17 02:20:36 +04:00
*
* 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 .
*
*/
2016-09-20 01:21:23 +03:00
# include <asm/unaligned.h>
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/timer.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/slab.h>
# include <linux/i2c.h>
# include <linux/workqueue.h>
2005-12-12 11:37:28 +03:00
2010-11-17 19:28:38 +03:00
# include <media/rc-core.h>
2015-11-10 17:01:44 +03:00
# include <media/i2c/ir-kbd-i2c.h>
2005-11-09 08:37:21 +03:00
2017-10-21 15:16:47 +03:00
# define FLAG_TX 1
# define FLAG_HDPVR 2
2005-04-17 02:20:36 +04:00
2017-10-25 00:04:16 +03:00
static bool enable_hdpvr ;
module_param ( enable_hdpvr , bool , 0644 ) ;
2017-08-07 23:20:58 +03:00
static int get_key_haup_common ( struct IR_i2c * ir , enum rc_proto * protocol ,
u32 * scancode , u8 * ptoggle , int size )
2005-04-17 02:20:36 +04:00
{
2007-06-25 21:34:06 +04:00
unsigned char buf [ 6 ] ;
2016-09-20 01:21:23 +03:00
int start , range , toggle , dev , code , ircode , vendor ;
2005-04-17 02:20:36 +04:00
/* poll IR chip */
2009-05-13 23:48:50 +04:00
if ( size ! = i2c_master_recv ( ir - > c , buf , size ) )
2005-04-17 02:20:36 +04:00
return - EIO ;
2016-09-20 01:21:23 +03:00
if ( buf [ 0 ] & 0x80 ) {
int offset = ( size = = 6 ) ? 3 : 0 ;
2005-04-17 02:20:36 +04:00
2016-09-20 01:21:23 +03:00
/* split rc5 data block ... */
start = ( buf [ offset ] > > 7 ) & 1 ;
range = ( buf [ offset ] > > 6 ) & 1 ;
toggle = ( buf [ offset ] > > 5 ) & 1 ;
dev = buf [ offset ] & 0x1f ;
code = ( buf [ offset + 1 ] > > 2 ) & 0x3f ;
2014-04-04 03:31:25 +04:00
2016-09-20 01:21:23 +03:00
/* rc5 has two start bits
* the first bit must be one
* the second bit defines the command range :
* 1 = 0 - 63 , 0 = 64 - 127
*/
if ( ! start )
/* no key pressed */
return 0 ;
2008-09-22 07:54:59 +04:00
2016-09-20 01:21:23 +03:00
/* filter out invalid key presses */
ircode = ( start < < 12 ) | ( toggle < < 11 ) | ( dev < < 6 ) | code ;
if ( ( ircode & 0x1fff ) = = 0x1fff )
return 0 ;
2006-09-26 23:39:00 +04:00
2016-09-20 01:21:23 +03:00
if ( ! range )
code + = 64 ;
2005-04-17 02:20:36 +04:00
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev ,
" ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d \n " ,
2016-09-20 01:21:23 +03:00
start , range , toggle , dev , code ) ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_RC5 ;
2016-09-20 01:21:23 +03:00
* scancode = RC_SCANCODE_RC5 ( dev , code ) ;
* ptoggle = toggle ;
return 1 ;
} else if ( size = = 6 & & ( buf [ 0 ] & 0x40 ) ) {
code = buf [ 4 ] ;
dev = buf [ 3 ] ;
vendor = get_unaligned_be16 ( buf + 1 ) ;
if ( vendor = = 0x800f ) {
* ptoggle = ( dev & 0x80 ) ! = 0 ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_RC6_MCE ;
2016-09-20 01:21:23 +03:00
dev & = 0x7f ;
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev ,
" ir hauppauge (rc6-mce): t%d vendor=%d dev=%d code=%d \n " ,
* ptoggle , vendor , dev , code ) ;
2016-09-20 01:21:23 +03:00
} else {
* ptoggle = 0 ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_RC6_6A_32 ;
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev ,
" ir hauppauge (rc6-6a-32): vendor=%d dev=%d code=%d \n " ,
vendor , dev , code ) ;
2016-09-20 01:21:23 +03:00
}
* scancode = RC_SCANCODE_RC6_6A ( vendor , dev , code ) ;
return 1 ;
}
return 0 ;
2005-04-17 02:20:36 +04:00
}
2017-08-07 23:20:58 +03:00
static int get_key_haup ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2007-06-25 21:34:06 +04:00
{
2016-09-20 01:21:23 +03:00
return get_key_haup_common ( ir , protocol , scancode , toggle , 3 ) ;
2007-06-25 21:34:06 +04:00
}
2017-08-07 23:20:58 +03:00
static int get_key_haup_xvr ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2007-06-25 21:34:06 +04:00
{
2011-01-21 00:31:18 +03:00
int ret ;
unsigned char buf [ 1 ] = { 0 } ;
/*
* This is the same apparent " are you ready? " poll command observed
* watching Windows driver traffic and implemented in lirc_zilog . With
* this added , we get far saner remote behavior with z8 chips on usb
* connected devices , even with the default polling interval of 100 ms .
*/
ret = i2c_master_send ( ir - > c , buf , 1 ) ;
if ( ret ! = 1 )
return ( ret < 0 ) ? ret : - EINVAL ;
2016-09-20 01:21:23 +03:00
return get_key_haup_common ( ir , protocol , scancode , toggle , 6 ) ;
2007-06-25 21:34:06 +04:00
}
2017-08-07 23:20:58 +03:00
static int get_key_pixelview ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2005-04-17 02:20:36 +04:00
{
2018-03-23 14:10:12 +03:00
int rc ;
2005-11-09 08:37:43 +03:00
unsigned char b ;
2005-04-17 02:20:36 +04:00
/* poll IR chip */
2018-03-23 14:10:12 +03:00
rc = i2c_master_recv ( ir - > c , & b , 1 ) ;
if ( rc ! = 1 ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read error \n " ) ;
2018-03-23 14:10:12 +03:00
if ( rc < 0 )
return rc ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
2014-04-04 03:31:25 +04:00
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_OTHER ;
2014-04-04 03:31:25 +04:00
* scancode = b ;
* toggle = 0 ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2017-08-07 23:20:58 +03:00
static int get_key_fusionhdtv ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2007-08-24 08:02:32 +04:00
{
2018-03-23 14:10:12 +03:00
int rc ;
2007-08-24 08:02:32 +04:00
unsigned char buf [ 4 ] ;
/* poll IR chip */
2018-03-23 14:10:12 +03:00
rc = i2c_master_recv ( ir - > c , buf , 4 ) ;
if ( rc ! = 4 ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read error \n " ) ;
2018-03-23 14:10:12 +03:00
if ( rc < 0 )
return rc ;
2007-08-24 08:02:32 +04:00
return - EIO ;
}
2017-10-18 17:00:50 +03:00
if ( buf [ 0 ] ! = 0 | | buf [ 1 ] ! = 0 | | buf [ 2 ] ! = 0 | | buf [ 3 ] ! = 0 )
dev_dbg ( & ir - > rc - > dev , " %s: %*ph \n " , __func__ , 4 , buf ) ;
2007-08-24 08:02:32 +04:00
/* no key pressed or signal from other ir remote */
if ( buf [ 0 ] ! = 0x1 | | buf [ 1 ] ! = 0xfe )
return 0 ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_UNKNOWN ;
2014-04-04 03:31:25 +04:00
* scancode = buf [ 2 ] ;
* toggle = 0 ;
2007-08-24 08:02:32 +04:00
return 1 ;
}
2017-08-07 23:20:58 +03:00
static int get_key_knc1 ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2005-04-17 02:20:36 +04:00
{
2018-03-23 14:10:12 +03:00
int rc ;
2005-04-17 02:20:36 +04:00
unsigned char b ;
/* poll IR chip */
2018-03-23 14:10:12 +03:00
rc = i2c_master_recv ( ir - > c , & b , 1 ) ;
if ( rc ! = 1 ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read error \n " ) ;
2018-03-23 14:10:12 +03:00
if ( rc < 0 )
return rc ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
/* it seems that 0xFE indicates that a button is still hold
2005-11-09 08:37:36 +03:00
down , while 0xff indicates that no button is hold
down . 0xfe sequences are sometimes interrupted by 0xFF */
2005-04-17 02:20:36 +04:00
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " key %02x \n " , b ) ;
2005-04-17 02:20:36 +04:00
2005-11-09 08:37:36 +03:00
if ( b = = 0xff )
2005-04-17 02:20:36 +04:00
return 0 ;
2005-11-09 08:37:36 +03:00
if ( b = = 0xfe )
2005-04-17 02:20:36 +04:00
/* keep old data */
return 1 ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_UNKNOWN ;
2014-04-04 03:31:25 +04:00
* scancode = b ;
* toggle = 0 ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2017-08-07 23:20:58 +03:00
static int get_key_avermedia_cardbus ( struct IR_i2c * ir , enum rc_proto * protocol ,
2014-04-04 03:31:25 +04:00
u32 * scancode , u8 * toggle )
2009-02-12 09:43:11 +03:00
{
unsigned char subaddr , key , keygroup ;
2009-05-13 23:48:50 +04:00
struct i2c_msg msg [ ] = { { . addr = ir - > c - > addr , . flags = 0 ,
2009-02-12 09:43:11 +03:00
. buf = & subaddr , . len = 1 } ,
2009-05-13 23:48:50 +04:00
{ . addr = ir - > c - > addr , . flags = I2C_M_RD ,
2009-02-12 09:43:11 +03:00
. buf = & key , . len = 1 } } ;
subaddr = 0x0d ;
2009-05-13 23:48:50 +04:00
if ( 2 ! = i2c_transfer ( ir - > c - > adapter , msg , 2 ) ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read error \n " ) ;
2009-02-12 09:43:11 +03:00
return - EIO ;
}
if ( key = = 0xff )
return 0 ;
subaddr = 0x0b ;
msg [ 1 ] . buf = & keygroup ;
2009-05-13 23:48:50 +04:00
if ( 2 ! = i2c_transfer ( ir - > c - > adapter , msg , 2 ) ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read error \n " ) ;
2009-02-12 09:43:11 +03:00
return - EIO ;
}
if ( keygroup = = 0xff )
return 0 ;
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " read key 0x%02x/0x%02x \n " , key , keygroup ) ;
2013-04-06 21:28:16 +04:00
if ( keygroup < 2 | | keygroup > 4 ) {
2017-10-18 17:00:50 +03:00
dev_warn ( & ir - > rc - > dev , " warning: invalid key group 0x%02x for key 0x%02x \n " ,
keygroup , key ) ;
2009-02-12 09:43:11 +03:00
}
key | = ( keygroup & 1 ) < < 6 ;
2017-08-07 23:20:58 +03:00
* protocol = RC_PROTO_UNKNOWN ;
2014-04-04 03:31:25 +04:00
* scancode = key ;
if ( ir - > c - > addr = = 0x41 ) /* AVerMedia EM78P153 */
* scancode | = keygroup < < 8 ;
* toggle = 0 ;
2009-02-12 09:43:11 +03:00
return 1 ;
}
2005-04-17 02:20:36 +04:00
/* ----------------------------------------------------------------------- */
2012-01-10 04:28:13 +04:00
static int ir_key_poll ( struct IR_i2c * ir )
2005-04-17 02:20:36 +04:00
{
2017-08-07 23:20:58 +03:00
enum rc_proto protocol ;
2014-04-04 03:31:25 +04:00
u32 scancode ;
u8 toggle ;
2005-04-17 02:20:36 +04:00
int rc ;
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " %s \n " , __func__ ) ;
2014-04-04 03:31:25 +04:00
rc = ir - > get_key ( ir , & protocol , & scancode , & toggle ) ;
2005-04-17 02:20:36 +04:00
if ( rc < 0 ) {
2017-10-18 17:00:50 +03:00
dev_warn ( & ir - > rc - > dev , " error %d \n " , rc ) ;
2012-01-10 04:28:13 +04:00
return rc ;
2005-04-17 02:20:36 +04:00
}
2011-01-12 19:50:01 +03:00
if ( rc ) {
2017-10-18 17:00:50 +03:00
dev_dbg ( & ir - > rc - > dev , " %s: proto = 0x%04x, scancode = 0x%08x \n " ,
2014-04-04 03:31:30 +04:00
__func__ , protocol , scancode ) ;
rc_keydown ( ir - > rc , protocol , scancode , toggle ) ;
2011-01-12 19:50:01 +03:00
}
2012-01-10 04:28:13 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-11-22 17:57:56 +03:00
static void ir_work ( struct work_struct * work )
2005-04-17 02:20:36 +04:00
{
2012-01-10 04:28:13 +04:00
int rc ;
2009-03-07 13:43:43 +03:00
struct IR_i2c * ir = container_of ( work , struct IR_i2c , work . work ) ;
2007-05-21 18:51:11 +04:00
2017-10-21 15:16:47 +03:00
/*
* If the transmit code is holding the lock , skip polling for
* IR , we ' ll get it to it next time round
*/
if ( mutex_trylock ( & ir - > lock ) ) {
rc = ir_key_poll ( ir ) ;
mutex_unlock ( & ir - > lock ) ;
if ( rc = = - ENODEV ) {
rc_unregister_device ( ir - > rc ) ;
ir - > rc = NULL ;
return ;
}
2012-01-10 04:28:13 +04:00
}
2010-09-23 08:23:10 +04:00
schedule_delayed_work ( & ir - > work , msecs_to_jiffies ( ir - > polling_interval ) ) ;
2005-04-17 02:20:36 +04:00
}
2017-10-17 23:31:20 +03:00
static int ir_open ( struct rc_dev * dev )
{
struct IR_i2c * ir = dev - > priv ;
schedule_delayed_work ( & ir - > work , 0 ) ;
return 0 ;
}
static void ir_close ( struct rc_dev * dev )
{
struct IR_i2c * ir = dev - > priv ;
cancel_delayed_work_sync ( & ir - > work ) ;
}
2017-10-21 15:16:47 +03:00
/* Zilog Transmit Interface */
# define XTAL_FREQ 18432000
# define ZILOG_SEND 0x80
# define ZILOG_UIR_END 0x40
# define ZILOG_INIT_END 0x20
# define ZILOG_LIR_END 0x10
# define ZILOG_STATUS_OK 0x80
# define ZILOG_STATUS_TX 0x40
# define ZILOG_STATUS_SET 0x20
/*
* As you can see here , very few different lengths of pulse and space
* can be encoded . This means that the hardware does not work well with
* recorded IR . It ' s best to work with generated IR , like from ir - ctl or
* the in - kernel encoders .
*/
struct code_block {
u8 length ;
u16 pulse [ 7 ] ; /* not aligned */
u8 carrier_pulse ;
u8 carrier_space ;
u16 space [ 8 ] ; /* not aligned */
u8 codes [ 61 ] ;
u8 csum [ 2 ] ;
} __packed ;
static int send_data_block ( struct IR_i2c * ir , int cmd ,
struct code_block * code_block )
{
int i , j , ret ;
u8 buf [ 5 ] , * p ;
p = & code_block - > length ;
for ( i = 0 ; p < code_block - > csum ; i + + )
code_block - > csum [ i & 1 ] ^ = * p + + ;
p = & code_block - > length ;
for ( i = 0 ; i < sizeof ( * code_block ) ; ) {
int tosend = sizeof ( * code_block ) - i ;
if ( tosend > 4 )
tosend = 4 ;
buf [ 0 ] = i + 1 ;
for ( j = 0 ; j < tosend ; + + j )
buf [ 1 + j ] = p [ i + j ] ;
dev_dbg ( & ir - > rc - > dev , " %*ph " , tosend + 1 , buf ) ;
ret = i2c_master_send ( ir - > tx_c , buf , tosend + 1 ) ;
if ( ret ! = tosend + 1 ) {
dev_dbg ( & ir - > rc - > dev ,
" i2c_master_send failed with %d \n " , ret ) ;
return ret < 0 ? ret : - EIO ;
}
i + = tosend ;
}
buf [ 0 ] = 0 ;
buf [ 1 ] = cmd ;
ret = i2c_master_send ( ir - > tx_c , buf , 2 ) ;
if ( ret ! = 2 ) {
dev_err ( & ir - > rc - > dev , " i2c_master_send failed with %d \n " , ret ) ;
return ret < 0 ? ret : - EIO ;
}
usleep_range ( 2000 , 5000 ) ;
ret = i2c_master_send ( ir - > tx_c , buf , 1 ) ;
if ( ret ! = 1 ) {
dev_err ( & ir - > rc - > dev , " i2c_master_send failed with %d \n " , ret ) ;
return ret < 0 ? ret : - EIO ;
}
return 0 ;
}
static int zilog_init ( struct IR_i2c * ir )
{
struct code_block code_block = { . length = sizeof ( code_block ) } ;
u8 buf [ 4 ] ;
int ret ;
put_unaligned_be16 ( 0x1000 , & code_block . pulse [ 3 ] ) ;
ret = send_data_block ( ir , ZILOG_INIT_END , & code_block ) ;
if ( ret )
return ret ;
ret = i2c_master_recv ( ir - > tx_c , buf , 4 ) ;
if ( ret ! = 4 ) {
dev_err ( & ir - > c - > dev , " failed to retrieve firmware version: %d \n " ,
ret ) ;
return ret < 0 ? ret : - EIO ;
}
dev_info ( & ir - > c - > dev , " Zilog/Hauppauge IR blaster firmware version %d.%d.%d \n " ,
buf [ 1 ] , buf [ 2 ] , buf [ 3 ] ) ;
return 0 ;
}
/*
* If the last slot for pulse is the same as the current slot for pulse ,
* then use slot no 7.
*/
static void copy_codes ( u8 * dst , u8 * src , unsigned int count )
{
u8 c , last = 0xff ;
while ( count - - ) {
c = * src + + ;
if ( ( c & 0xf0 ) = = last ) {
* dst + + = 0x70 | ( c & 0xf ) ;
} else {
* dst + + = c ;
last = c & 0xf0 ;
}
}
}
/*
* When looking for repeats , we don ' t care about the trailing space . This
* is set to the shortest possible anyway .
*/
static int cmp_no_trail ( u8 * a , u8 * b , unsigned int count )
{
while ( - - count ) {
if ( * a + + ! = * b + + )
return 1 ;
}
return ( * a & 0xf0 ) - ( * b & 0xf0 ) ;
}
static int find_slot ( u16 * array , unsigned int size , u16 val )
{
int i ;
for ( i = 0 ; i < size ; i + + ) {
if ( get_unaligned_be16 ( & array [ i ] ) = = val ) {
return i ;
} else if ( ! array [ i ] ) {
put_unaligned_be16 ( val , & array [ i ] ) ;
return i ;
}
}
return - 1 ;
}
static int zilog_ir_format ( struct rc_dev * rcdev , unsigned int * txbuf ,
unsigned int count , struct code_block * code_block )
{
struct IR_i2c * ir = rcdev - > priv ;
int rep , i , l , p = 0 , s , c = 0 ;
bool repeating ;
u8 codes [ 174 ] ;
code_block - > carrier_pulse = DIV_ROUND_CLOSEST (
ir - > duty_cycle * XTAL_FREQ / 1000 , ir - > carrier ) ;
code_block - > carrier_space = DIV_ROUND_CLOSEST (
( 100 - ir - > duty_cycle ) * XTAL_FREQ / 1000 , ir - > carrier ) ;
for ( i = 0 ; i < count ; i + + ) {
if ( c > = ARRAY_SIZE ( codes ) - 1 ) {
dev_warn ( & rcdev - > dev , " IR too long, cannot transmit \n " ) ;
return - EINVAL ;
}
/*
* Lengths more than 142220u s cannot be encoded ; also
* this checks for multiply overflow
*/
if ( txbuf [ i ] > 142220 )
return - EINVAL ;
l = DIV_ROUND_CLOSEST ( ( XTAL_FREQ / 1000 ) * txbuf [ i ] , 40000 ) ;
if ( i & 1 ) {
s = find_slot ( code_block - > space ,
ARRAY_SIZE ( code_block - > space ) , l ) ;
if ( s = = - 1 ) {
dev_warn ( & rcdev - > dev , " Too many different lengths spaces, cannot transmit " ) ;
return - EINVAL ;
}
/* We have a pulse and space */
codes [ c + + ] = ( p < < 4 ) | s ;
} else {
p = find_slot ( code_block - > pulse ,
ARRAY_SIZE ( code_block - > pulse ) , l ) ;
if ( p = = - 1 ) {
dev_warn ( & rcdev - > dev , " Too many different lengths pulses, cannot transmit " ) ;
return - EINVAL ;
}
}
}
/* We have to encode the trailing pulse. Find the shortest space */
s = 0 ;
for ( i = 1 ; i < ARRAY_SIZE ( code_block - > space ) ; i + + ) {
u16 d = get_unaligned_be16 ( & code_block - > space [ i ] ) ;
if ( get_unaligned_be16 ( & code_block - > space [ s ] ) > d )
s = i ;
}
codes [ c + + ] = ( p < < 4 ) | s ;
dev_dbg ( & rcdev - > dev , " generated %d codes \n " , c ) ;
/*
* Are the last N codes ( so pulse + space ) repeating 3 times ?
* if so we can shorten the codes list and use code 0xc0 to repeat
* them .
*/
repeating = false ;
for ( rep = c / 3 ; rep > = 1 ; rep - - ) {
if ( ! memcmp ( & codes [ c - rep * 3 ] , & codes [ c - rep * 2 ] , rep ) & &
! cmp_no_trail ( & codes [ c - rep ] , & codes [ c - rep * 2 ] , rep ) ) {
repeating = true ;
break ;
}
}
if ( repeating ) {
/* first copy any leading non-repeating */
int leading = c - rep * 3 ;
2018-03-23 14:13:06 +03:00
if ( leading > = ARRAY_SIZE ( code_block - > codes ) - 3 - rep ) {
2017-10-21 15:16:47 +03:00
dev_warn ( & rcdev - > dev , " IR too long, cannot transmit \n " ) ;
return - EINVAL ;
}
dev_dbg ( & rcdev - > dev , " found trailing %d repeat \n " , rep ) ;
copy_codes ( code_block - > codes , codes , leading ) ;
code_block - > codes [ leading ] = 0x82 ;
copy_codes ( code_block - > codes + leading + 1 , codes + leading ,
rep ) ;
c = leading + 1 + rep ;
code_block - > codes [ c + + ] = 0xc0 ;
} else {
if ( c > = ARRAY_SIZE ( code_block - > codes ) - 3 ) {
dev_warn ( & rcdev - > dev , " IR too long, cannot transmit \n " ) ;
return - EINVAL ;
}
dev_dbg ( & rcdev - > dev , " found no trailing repeat \n " ) ;
code_block - > codes [ 0 ] = 0x82 ;
copy_codes ( code_block - > codes + 1 , codes , c ) ;
c + + ;
code_block - > codes [ c + + ] = 0xc4 ;
}
while ( c < ARRAY_SIZE ( code_block - > codes ) )
code_block - > codes [ c + + ] = 0x83 ;
return 0 ;
}
static int zilog_tx ( struct rc_dev * rcdev , unsigned int * txbuf ,
unsigned int count )
{
struct IR_i2c * ir = rcdev - > priv ;
struct code_block code_block = { . length = sizeof ( code_block ) } ;
u8 buf [ 2 ] ;
int ret , i ;
ret = zilog_ir_format ( rcdev , txbuf , count , & code_block ) ;
if ( ret )
return ret ;
ret = mutex_lock_interruptible ( & ir - > lock ) ;
if ( ret )
return ret ;
ret = send_data_block ( ir , ZILOG_UIR_END , & code_block ) ;
if ( ret )
goto out_unlock ;
ret = i2c_master_recv ( ir - > tx_c , buf , 1 ) ;
if ( ret ! = 1 ) {
dev_err ( & ir - > rc - > dev , " i2c_master_recv failed with %d \n " , ret ) ;
goto out_unlock ;
}
dev_dbg ( & ir - > rc - > dev , " code set status: %02x \n " , buf [ 0 ] ) ;
if ( buf [ 0 ] ! = ( ZILOG_STATUS_OK | ZILOG_STATUS_SET ) ) {
dev_err ( & ir - > rc - > dev , " unexpected IR TX response %02x \n " ,
buf [ 0 ] ) ;
ret = - EIO ;
goto out_unlock ;
}
buf [ 0 ] = 0x00 ;
buf [ 1 ] = ZILOG_SEND ;
ret = i2c_master_send ( ir - > tx_c , buf , 2 ) ;
if ( ret ! = 2 ) {
dev_err ( & ir - > rc - > dev , " i2c_master_send failed with %d \n " , ret ) ;
if ( ret > = 0 )
ret = - EIO ;
goto out_unlock ;
}
dev_dbg ( & ir - > rc - > dev , " send command sent \n " ) ;
/*
* This bit NAKs until the device is ready , so we retry it
* sleeping a bit each time . This seems to be what the windows
* driver does , approximately .
* Try for up to 1 s .
*/
for ( i = 0 ; i < 20 ; + + i ) {
set_current_state ( TASK_UNINTERRUPTIBLE ) ;
schedule_timeout ( msecs_to_jiffies ( 50 ) ) ;
ret = i2c_master_send ( ir - > tx_c , buf , 1 ) ;
if ( ret = = 1 )
break ;
dev_dbg ( & ir - > rc - > dev ,
" NAK expected: i2c_master_send failed with %d (try %d) \n " ,
ret , i + 1 ) ;
}
if ( ret ! = 1 ) {
dev_err ( & ir - > rc - > dev ,
" IR TX chip never got ready: last i2c_master_send failed with %d \n " ,
ret ) ;
if ( ret > = 0 )
ret = - EIO ;
goto out_unlock ;
}
i = i2c_master_recv ( ir - > tx_c , buf , 1 ) ;
if ( i ! = 1 ) {
dev_err ( & ir - > rc - > dev , " i2c_master_recv failed with %d \n " , ret ) ;
ret = - EIO ;
goto out_unlock ;
} else if ( buf [ 0 ] ! = ZILOG_STATUS_OK ) {
dev_err ( & ir - > rc - > dev , " unexpected IR TX response #2: %02x \n " ,
buf [ 0 ] ) ;
ret = - EIO ;
goto out_unlock ;
}
dev_dbg ( & ir - > rc - > dev , " transmit complete \n " ) ;
/* Oh good, it worked */
ret = count ;
out_unlock :
mutex_unlock ( & ir - > lock ) ;
return ret ;
}
static int zilog_tx_carrier ( struct rc_dev * dev , u32 carrier )
{
struct IR_i2c * ir = dev - > priv ;
if ( carrier > 500000 | | carrier < 20000 )
return - EINVAL ;
ir - > carrier = carrier ;
return 0 ;
}
static int zilog_tx_duty_cycle ( struct rc_dev * dev , u32 duty_cycle )
{
struct IR_i2c * ir = dev - > priv ;
ir - > duty_cycle = duty_cycle ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2009-05-13 23:48:50 +04:00
static int ir_probe ( struct i2c_client * client , const struct i2c_device_id * id )
2005-04-17 02:20:36 +04:00
{
2010-04-03 03:01:00 +04:00
char * ir_codes = NULL ;
2009-05-13 23:50:11 +04:00
const char * name = NULL ;
2017-08-07 23:20:58 +03:00
u64 rc_proto = RC_PROTO_BIT_UNKNOWN ;
2005-12-12 11:37:27 +03:00
struct IR_i2c * ir ;
2010-11-12 15:02:40 +03:00
struct rc_dev * rc = NULL ;
2009-05-13 23:48:50 +04:00
struct i2c_adapter * adap = client - > adapter ;
unsigned short addr = client - > addr ;
2018-05-03 13:38:40 +03:00
bool probe_tx = ( id - > driver_data & FLAG_TX ) ! = 0 ;
2006-11-20 16:23:04 +03:00
int err ;
2005-04-17 02:20:36 +04:00
2017-10-25 00:04:16 +03:00
if ( ( id - > driver_data & FLAG_HDPVR ) & & ! enable_hdpvr ) {
dev_err ( & client - > dev , " IR for HDPVR is known to cause problems during recording, use enable_hdpvr modparam to enable \n " ) ;
return - ENODEV ;
}
2013-05-02 15:29:43 +04:00
ir = devm_kzalloc ( & client - > dev , sizeof ( * ir ) , GFP_KERNEL ) ;
2010-11-12 15:02:40 +03:00
if ( ! ir )
return - ENOMEM ;
2005-09-15 11:01:53 +04:00
2009-05-13 23:48:50 +04:00
ir - > c = client ;
2010-09-23 08:23:10 +04:00
ir - > polling_interval = DEFAULT_POLLING_INTERVAL ;
2009-05-13 23:48:50 +04:00
i2c_set_clientdata ( client , ir ) ;
2006-01-09 20:25:21 +03:00
2005-04-17 02:20:36 +04:00
switch ( addr ) {
case 0x64 :
name = " Pixelview " ;
ir - > get_key = get_key_pixelview ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_OTHER ;
2010-04-03 03:01:00 +04:00
ir_codes = RC_MAP_EMPTY ;
2005-04-17 02:20:36 +04:00
break ;
case 0x18 :
2009-11-13 11:48:24 +03:00
case 0x1f :
2005-04-17 02:20:36 +04:00
case 0x1a :
name = " Hauppauge " ;
ir - > get_key = get_key_haup ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_RC5 ;
2011-01-25 04:23:08 +03:00
ir_codes = RC_MAP_HAUPPAUGE ;
2005-04-17 02:20:36 +04:00
break ;
case 0x30 :
2005-11-09 08:37:32 +03:00
name = " KNC One " ;
ir - > get_key = get_key_knc1 ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_OTHER ;
2010-04-03 03:01:00 +04:00
ir_codes = RC_MAP_EMPTY ;
2005-04-17 02:20:36 +04:00
break ;
2007-08-24 08:02:32 +04:00
case 0x6b :
2007-08-24 08:07:12 +04:00
name = " FusionHDTV " ;
ir - > get_key = get_key_fusionhdtv ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_UNKNOWN ;
2010-04-03 03:01:00 +04:00
ir_codes = RC_MAP_FUSIONHDTV_MCE ;
2007-08-24 08:02:32 +04:00
break ;
2009-02-12 09:43:11 +03:00
case 0x40 :
name = " AVerMedia Cardbus remote " ;
ir - > get_key = get_key_avermedia_cardbus ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_OTHER ;
2010-04-03 03:01:00 +04:00
ir_codes = RC_MAP_AVERMEDIA_CARDBUS ;
2009-02-12 09:43:11 +03:00
break ;
2013-04-06 21:28:16 +04:00
case 0x41 :
name = " AVerMedia EM78P153 " ;
ir - > get_key = get_key_avermedia_cardbus ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_OTHER ;
2013-04-06 21:28:16 +04:00
/* RM-KV remote, seems to be same as RM-K6 */
ir_codes = RC_MAP_AVERMEDIA_M733A_RM_K6 ;
break ;
2011-01-16 21:45:32 +03:00
case 0x71 :
name = " Hauppauge/Zilog Z8 " ;
ir - > get_key = get_key_haup_xvr ;
2017-08-07 23:20:58 +03:00
rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
RC_PROTO_BIT_RC6_6A_32 ;
2011-01-25 04:23:08 +03:00
ir_codes = RC_MAP_HAUPPAUGE ;
2018-05-03 13:38:40 +03:00
probe_tx = true ;
2011-01-16 21:45:32 +03:00
break ;
2005-04-17 02:20:36 +04:00
}
2009-05-13 23:49:32 +04:00
/* Let the caller override settings */
if ( client - > dev . platform_data ) {
const struct IR_i2c_init_data * init_data =
client - > dev . platform_data ;
ir_codes = init_data - > ir_codes ;
2010-11-12 15:02:40 +03:00
rc = init_data - > rc_dev ;
2009-05-13 23:49:32 +04:00
name = init_data - > name ;
2009-07-28 18:44:05 +04:00
if ( init_data - > type )
2017-08-07 23:20:58 +03:00
rc_proto = init_data - > type ;
2009-07-28 18:44:05 +04:00
2010-09-23 08:23:10 +04:00
if ( init_data - > polling_interval )
ir - > polling_interval = init_data - > polling_interval ;
2009-07-28 18:44:05 +04:00
switch ( init_data - > internal_get_key_func ) {
case IR_KBD_GET_KEY_CUSTOM :
/* The bridge driver provided us its own function */
ir - > get_key = init_data - > get_key ;
break ;
case IR_KBD_GET_KEY_PIXELVIEW :
ir - > get_key = get_key_pixelview ;
break ;
case IR_KBD_GET_KEY_HAUP :
ir - > get_key = get_key_haup ;
break ;
case IR_KBD_GET_KEY_KNC1 :
ir - > get_key = get_key_knc1 ;
break ;
case IR_KBD_GET_KEY_FUSIONHDTV :
ir - > get_key = get_key_fusionhdtv ;
break ;
case IR_KBD_GET_KEY_HAUP_XVR :
ir - > get_key = get_key_haup_xvr ;
break ;
case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS :
ir - > get_key = get_key_avermedia_cardbus ;
break ;
}
2009-05-13 23:49:32 +04:00
}
2010-11-12 15:02:40 +03:00
if ( ! rc ) {
/*
2013-10-21 04:34:01 +04:00
* If platform_data doesn ' t specify rc_dev , initialize it
2010-11-12 15:02:40 +03:00
* internally
*/
2016-12-16 11:50:58 +03:00
rc = rc_allocate_device ( RC_DRIVER_SCANCODE ) ;
2013-05-02 15:29:43 +04:00
if ( ! rc )
return - ENOMEM ;
2010-11-12 15:02:40 +03:00
}
ir - > rc = rc ;
2009-05-13 23:50:11 +04:00
/* Make sure we are all setup before going on */
2017-08-07 23:20:58 +03:00
if ( ! name | | ! ir - > get_key | | ! rc_proto | | ! ir_codes ) {
2017-10-18 17:00:50 +03:00
dev_warn ( & client - > dev , " Unsupported device at address 0x%02x \n " ,
addr ) ;
2009-05-13 23:50:11 +04:00
err = - ENODEV ;
goto err_out_free ;
}
2006-11-20 16:23:04 +03:00
ir - > ir_codes = ir_codes ;
2005-11-09 08:37:32 +03:00
2017-10-18 16:39:12 +03:00
snprintf ( ir - > phys , sizeof ( ir - > phys ) , " %s/%s " , dev_name ( & adap - > dev ) ,
2009-05-13 23:48:50 +04:00
dev_name ( & client - > dev ) ) ;
2005-11-09 08:37:56 +03:00
2010-11-12 15:02:40 +03:00
/*
* Initialize input_dev fields
* It doesn ' t make sense to allow overriding them via platform_data
*/
2010-10-29 23:08:23 +04:00
rc - > input_id . bustype = BUS_I2C ;
rc - > input_phys = ir - > phys ;
2017-10-18 16:39:12 +03:00
rc - > device_name = name ;
rc - > dev . parent = & client - > dev ;
2017-10-17 23:31:20 +03:00
rc - > priv = ir ;
rc - > open = ir_open ;
rc - > close = ir_close ;
2010-11-12 15:02:40 +03:00
/*
* Initialize the other fields of rc_dev
*/
rc - > map_name = ir - > ir_codes ;
2017-08-07 23:20:58 +03:00
rc - > allowed_protocols = rc_proto ;
2010-11-12 15:02:40 +03:00
if ( ! rc - > driver_name )
2017-10-18 17:00:50 +03:00
rc - > driver_name = KBUILD_MODNAME ;
2005-09-15 11:01:53 +04:00
2017-10-21 15:16:47 +03:00
mutex_init ( & ir - > lock ) ;
2017-10-17 23:31:20 +03:00
INIT_DELAYED_WORK ( & ir - > work , ir_work ) ;
2018-05-03 13:38:40 +03:00
if ( probe_tx ) {
2017-10-21 15:16:47 +03:00
ir - > tx_c = i2c_new_dummy ( client - > adapter , 0x70 ) ;
if ( ! ir - > tx_c ) {
dev_err ( & client - > dev , " failed to setup tx i2c address " ) ;
} else if ( ! zilog_init ( ir ) ) {
ir - > carrier = 38000 ;
ir - > duty_cycle = 40 ;
rc - > tx_ir = zilog_tx ;
rc - > s_tx_carrier = zilog_tx_carrier ;
rc - > s_tx_duty_cycle = zilog_tx_duty_cycle ;
}
}
2010-10-29 23:08:23 +04:00
err = rc_register_device ( rc ) ;
2006-11-20 16:23:04 +03:00
if ( err )
2009-05-13 23:48:50 +04:00
goto err_out_free ;
2006-11-20 16:23:04 +03:00
2005-04-17 02:20:36 +04:00
return 0 ;
2006-11-20 16:23:04 +03:00
err_out_free :
2017-10-21 15:16:47 +03:00
if ( ir - > tx_c )
i2c_unregister_device ( ir - > tx_c ) ;
2010-11-12 15:02:40 +03:00
/* Only frees rc if it were allocated internally */
2010-10-29 23:08:23 +04:00
rc_free_device ( rc ) ;
2006-11-20 16:23:04 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
2009-05-13 23:48:50 +04:00
static int ir_remove ( struct i2c_client * client )
2005-04-17 02:20:36 +04:00
{
2005-11-09 08:37:43 +03:00
struct IR_i2c * ir = i2c_get_clientdata ( client ) ;
2005-04-17 02:20:36 +04:00
/* kill outstanding polls */
2009-03-07 13:43:43 +03:00
cancel_delayed_work_sync ( & ir - > work ) ;
2005-04-17 02:20:36 +04:00
2017-10-21 15:16:47 +03:00
if ( ir - > tx_c )
i2c_unregister_device ( ir - > tx_c ) ;
2009-05-13 23:48:50 +04:00
/* unregister device */
2014-11-20 13:13:16 +03:00
rc_unregister_device ( ir - > rc ) ;
2005-04-17 02:20:36 +04:00
/* free memory */
return 0 ;
}
2009-05-13 23:48:50 +04:00
static const struct i2c_device_id ir_kbd_id [ ] = {
/* Generic entry for any IR receiver */
{ " ir_video " , 0 } ,
2009-07-28 18:50:14 +04:00
/* IR device specific entries should be added here */
2017-10-21 15:16:47 +03:00
{ " ir_z8f0811_haup " , FLAG_TX } ,
{ " ir_z8f0811_hdpvr " , FLAG_TX | FLAG_HDPVR } ,
2009-05-13 23:48:50 +04:00
{ }
} ;
2017-10-25 00:04:16 +03:00
MODULE_DEVICE_TABLE ( i2c , ir_kbd_id ) ;
2009-02-12 09:43:11 +03:00
2012-02-12 13:56:32 +04:00
static struct i2c_driver ir_kbd_driver = {
2009-05-13 23:48:50 +04:00
. driver = {
. name = " ir-kbd-i2c " ,
} ,
. probe = ir_probe ,
. remove = ir_remove ,
. id_table = ir_kbd_id ,
} ;
2005-04-17 02:20:36 +04:00
2012-02-12 13:56:32 +04:00
module_i2c_driver ( ir_kbd_driver ) ;
2005-04-17 02:20:36 +04:00
/* ----------------------------------------------------------------------- */
MODULE_AUTHOR ( " Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller " ) ;
MODULE_DESCRIPTION ( " input driver for i2c IR remote controls " ) ;
MODULE_LICENSE ( " GPL " ) ;