2017-12-01 08:47:08 -05:00
// SPDX-License-Identifier: GPL-2.0
// ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol
//
// Copyright (C) 2011 by Mauro Carvalho Chehab
//
// This protocol uses the NEC protocol timings. However, data is formatted as:
// 13 bits Custom Code
// 13 bits NOT(Custom Code)
// 8 bits Key data
// 8 bits NOT(Key data)
//
// According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
// Information for this protocol is available at the Sanyo LC7461 datasheet.
2011-11-23 12:04:08 -03:00
2011-11-24 08:47:51 -03:00
# include <linux/module.h>
2011-11-23 12:04:08 -03:00
# include <linux/bitrev.h>
# include "rc-core-priv.h"
# define SANYO_NBITS (13+13+8+8)
# define SANYO_UNIT 562500 /* ns */
# define SANYO_HEADER_PULSE (16 * SANYO_UNIT)
# define SANYO_HEADER_SPACE (8 * SANYO_UNIT)
# define SANYO_BIT_PULSE (1 * SANYO_UNIT)
# define SANYO_BIT_0_SPACE (1 * SANYO_UNIT)
# define SANYO_BIT_1_SPACE (3 * SANYO_UNIT)
# define SANYO_REPEAT_SPACE (150 * SANYO_UNIT)
# define SANYO_TRAILER_PULSE (1 * SANYO_UNIT)
# define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */
enum sanyo_state {
STATE_INACTIVE ,
STATE_HEADER_SPACE ,
STATE_BIT_PULSE ,
STATE_BIT_SPACE ,
STATE_TRAILER_PULSE ,
STATE_TRAILER_SPACE ,
} ;
/**
* ir_sanyo_decode ( ) - Decode one SANYO pulse or space
* @ dev : the struct rc_dev descriptor of the device
2017-11-29 03:46:30 -05:00
* @ ev : the struct ir_raw_event descriptor of the pulse / space
2011-11-23 12:04:08 -03:00
*
* This function returns - EINVAL if the pulse violates the state machine
*/
static int ir_sanyo_decode ( struct rc_dev * dev , struct ir_raw_event ev )
{
struct sanyo_dec * data = & dev - > raw - > sanyo ;
u32 scancode ;
2016-11-09 14:13:34 -02:00
u16 address ;
u8 command , not_command ;
2011-11-23 12:04:08 -03:00
if ( ! is_timing_event ( ev ) ) {
if ( ev . reset ) {
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO event reset received. reset to state 0 \n " ) ;
2011-11-23 12:04:08 -03:00
data - > state = STATE_INACTIVE ;
}
return 0 ;
}
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO decode started at state %d (%uus %s) \n " ,
data - > state , TO_US ( ev . duration ) , TO_STR ( ev . pulse ) ) ;
2011-11-23 12:04:08 -03:00
switch ( data - > state ) {
case STATE_INACTIVE :
if ( ! ev . pulse )
break ;
if ( eq_margin ( ev . duration , SANYO_HEADER_PULSE , SANYO_UNIT / 2 ) ) {
data - > count = 0 ;
data - > state = STATE_HEADER_SPACE ;
return 0 ;
}
break ;
case STATE_HEADER_SPACE :
if ( ev . pulse )
break ;
if ( eq_margin ( ev . duration , SANYO_HEADER_SPACE , SANYO_UNIT / 2 ) ) {
data - > state = STATE_BIT_PULSE ;
return 0 ;
}
break ;
case STATE_BIT_PULSE :
if ( ! ev . pulse )
break ;
if ( ! eq_margin ( ev . duration , SANYO_BIT_PULSE , SANYO_UNIT / 2 ) )
break ;
data - > state = STATE_BIT_SPACE ;
return 0 ;
case STATE_BIT_SPACE :
if ( ev . pulse )
break ;
if ( ! data - > count & & geq_margin ( ev . duration , SANYO_REPEAT_SPACE , SANYO_UNIT / 2 ) ) {
2017-06-22 15:23:54 -04:00
rc_repeat ( dev ) ;
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO repeat last key \n " ) ;
2017-06-22 15:23:54 -04:00
data - > state = STATE_INACTIVE ;
2011-11-23 12:04:08 -03:00
return 0 ;
}
data - > bits < < = 1 ;
if ( eq_margin ( ev . duration , SANYO_BIT_1_SPACE , SANYO_UNIT / 2 ) )
data - > bits | = 1 ;
else if ( ! eq_margin ( ev . duration , SANYO_BIT_0_SPACE , SANYO_UNIT / 2 ) )
break ;
data - > count + + ;
if ( data - > count = = SANYO_NBITS )
data - > state = STATE_TRAILER_PULSE ;
else
data - > state = STATE_BIT_PULSE ;
return 0 ;
case STATE_TRAILER_PULSE :
if ( ! ev . pulse )
break ;
if ( ! eq_margin ( ev . duration , SANYO_TRAILER_PULSE , SANYO_UNIT / 2 ) )
break ;
data - > state = STATE_TRAILER_SPACE ;
return 0 ;
case STATE_TRAILER_SPACE :
if ( ev . pulse )
break ;
if ( ! geq_margin ( ev . duration , SANYO_TRAILER_SPACE , SANYO_UNIT / 2 ) )
break ;
address = bitrev16 ( ( data - > bits > > 29 ) & 0x1fff ) > > 3 ;
2012-05-14 10:22:58 -03:00
/* not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; */
2011-11-23 12:04:08 -03:00
command = bitrev8 ( ( data - > bits > > 8 ) & 0xff ) ;
not_command = bitrev8 ( ( data - > bits > > 0 ) & 0xff ) ;
if ( ( command ^ not_command ) ! = 0xff ) {
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO checksum error: received 0x%08llx \n " ,
data - > bits ) ;
2011-11-23 12:04:08 -03:00
data - > state = STATE_INACTIVE ;
return 0 ;
}
scancode = address < < 8 | command ;
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO scancode: 0x%06x \n " , scancode ) ;
2017-08-07 16:20:58 -04:00
rc_keydown ( dev , RC_PROTO_SANYO , scancode , 0 ) ;
2011-11-23 12:04:08 -03:00
data - > state = STATE_INACTIVE ;
return 0 ;
}
2018-02-12 07:20:52 -05:00
dev_dbg ( & dev - > dev , " SANYO decode failed at count %d state %d (%uus %s) \n " ,
data - > count , data - > state , TO_US ( ev . duration ) , TO_STR ( ev . pulse ) ) ;
2011-11-23 12:04:08 -03:00
data - > state = STATE_INACTIVE ;
return - EINVAL ;
}
2016-12-06 18:01:05 -02:00
static const struct ir_raw_timings_pd ir_sanyo_timings = {
. header_pulse = SANYO_HEADER_PULSE ,
. header_space = SANYO_HEADER_SPACE ,
. bit_pulse = SANYO_BIT_PULSE ,
. bit_space [ 0 ] = SANYO_BIT_0_SPACE ,
. bit_space [ 1 ] = SANYO_BIT_1_SPACE ,
. trailer_pulse = SANYO_TRAILER_PULSE ,
. trailer_space = SANYO_TRAILER_SPACE ,
. msb_first = 1 ,
} ;
/**
* ir_sanyo_encode ( ) - Encode a scancode as a stream of raw events
*
* @ protocol : protocol to encode
* @ scancode : scancode to encode
* @ events : array of raw ir events to write into
* @ max : maximum size of @ events
*
* Returns : The number of events written .
* - ENOBUFS if there isn ' t enough space in the array to fit the
* encoding . In this case all @ max events will have been written .
*/
2017-08-07 16:20:58 -04:00
static int ir_sanyo_encode ( enum rc_proto protocol , u32 scancode ,
2016-12-06 18:01:05 -02:00
struct ir_raw_event * events , unsigned int max )
{
struct ir_raw_event * e = events ;
int ret ;
u64 raw ;
raw = ( ( u64 ) ( bitrev16 ( scancode > > 8 ) & 0xfff8 ) < < ( 8 + 8 + 13 - 3 ) ) |
( ( u64 ) ( bitrev16 ( ~ scancode > > 8 ) & 0xfff8 ) < < ( 8 + 8 + 0 - 3 ) ) |
( ( bitrev8 ( scancode ) & 0xff ) < < 8 ) |
( bitrev8 ( ~ scancode ) & 0xff ) ;
ret = ir_raw_gen_pd ( & e , max , & ir_sanyo_timings , SANYO_NBITS , raw ) ;
if ( ret < 0 )
return ret ;
return e - events ;
}
2011-11-23 12:04:08 -03:00
static struct ir_raw_handler sanyo_handler = {
2017-08-07 16:20:58 -04:00
. protocols = RC_PROTO_BIT_SANYO ,
2011-11-23 12:04:08 -03:00
. decode = ir_sanyo_decode ,
2016-12-06 18:01:05 -02:00
. encode = ir_sanyo_encode ,
2017-02-25 06:51:30 -05:00
. carrier = 38000 ,
2018-03-23 16:47:37 -04:00
. min_timeout = SANYO_TRAILER_SPACE ,
2011-11-23 12:04:08 -03:00
} ;
static int __init ir_sanyo_decode_init ( void )
{
ir_raw_handler_register ( & sanyo_handler ) ;
printk ( KERN_INFO " IR SANYO protocol handler initialized \n " ) ;
return 0 ;
}
static void __exit ir_sanyo_decode_exit ( void )
{
ir_raw_handler_unregister ( & sanyo_handler ) ;
}
module_init ( ir_sanyo_decode_init ) ;
module_exit ( ir_sanyo_decode_exit ) ;
2017-12-01 08:47:08 -05:00
MODULE_LICENSE ( " GPL v2 " ) ;
2014-02-07 08:03:07 -02:00
MODULE_AUTHOR ( " Mauro Carvalho Chehab " ) ;
2011-11-23 12:04:08 -03:00
MODULE_AUTHOR ( " Red Hat Inc. (http://www.redhat.com) " ) ;
MODULE_DESCRIPTION ( " SANYO IR protocol decoder " ) ;