2010-03-20 20:59:44 -03:00
/* ir-raw-event.c - handle IR Pulse/Space event
*
* Copyright ( C ) 2010 by Mauro Carvalho Chehab < mchehab @ redhat . com >
*
* 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 version 2 of the License .
*
* 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 .
*/
# include <media/ir-core.h>
/* Start time: 4.5 ms */
# define MIN_START_TIME 3900000
# define MAX_START_TIME 5100000
/* Pulse time: 560 us */
# define MIN_PULSE_TIME 460000
# define MAX_PULSE_TIME 660000
/* Bit 1 space time: 2.25ms-560 us */
# define MIN_BIT1_TIME 1490000
# define MAX_BIT1_TIME 1890000
/* Bit 0 space time: 1.12ms-560 us */
# define MIN_BIT0_TIME 360000
# define MAX_BIT0_TIME 760000
2010-03-21 12:24:24 -03:00
/**
* __ir_nec_decode ( ) - Decode one NEC pulsecode
* @ input_dev : the struct input_dev descriptor of the device
* @ evs : event array with type / duration of pulse / space
* @ len : length of the array
* @ pos : position to start seeking for a code
* This function returns the decoded ircode or - EINVAL if no pulse got decoded
*/
static int __ir_nec_decode ( struct input_dev * input_dev ,
struct ir_raw_event * evs ,
int len , int * pos )
2010-03-20 20:59:44 -03:00
{
2010-03-21 12:24:24 -03:00
int count = - 1 ;
2010-03-20 20:59:44 -03:00
int ircode = 0 , not_code = 0 ;
/* Be sure that the first event is an start one and is a pulse */
2010-03-21 12:24:24 -03:00
for ( ; * pos < len ; ( * pos ) + + ) {
if ( evs [ * pos ] . type & ( IR_START_EVENT | IR_PULSE ) )
2010-03-20 20:59:44 -03:00
break ;
}
2010-03-21 12:24:24 -03:00
( * pos ) + + ; /* First event doesn't contain data */
2010-03-20 20:59:44 -03:00
2010-03-21 12:24:24 -03:00
if ( * pos > = len )
2010-03-20 20:59:44 -03:00
return 0 ;
/* First space should have 4.5 ms otherwise is not NEC protocol */
2010-03-21 12:24:24 -03:00
if ( ( evs [ * pos ] . delta . tv_nsec < MIN_START_TIME ) |
( evs [ * pos ] . delta . tv_nsec > MAX_START_TIME ) |
( evs [ * pos ] . type ! = IR_SPACE ) )
2010-03-20 20:59:44 -03:00
goto err ;
/*
* FIXME : need to implement the repeat sequence
*/
count = 0 ;
2010-03-21 12:24:24 -03:00
for ( ( * pos ) + + ; * pos < len ; ( * pos ) + + ) {
2010-03-20 20:59:44 -03:00
int bit ;
2010-03-21 12:24:24 -03:00
if ( ( evs [ * pos ] . delta . tv_nsec < MIN_PULSE_TIME ) |
( evs [ * pos ] . delta . tv_nsec > MAX_PULSE_TIME ) |
( evs [ * pos ] . type ! = IR_PULSE ) )
2010-03-20 20:59:44 -03:00
goto err ;
2010-03-21 12:24:24 -03:00
if ( + + * pos > = len )
2010-03-20 20:59:44 -03:00
goto err ;
2010-03-21 12:24:24 -03:00
if ( evs [ * pos ] . type ! = IR_SPACE )
2010-03-20 20:59:44 -03:00
goto err ;
2010-03-21 12:24:24 -03:00
if ( ( evs [ * pos ] . delta . tv_nsec > MIN_BIT1_TIME ) & &
( evs [ * pos ] . delta . tv_nsec < MAX_BIT1_TIME ) )
2010-03-20 20:59:44 -03:00
bit = 1 ;
2010-03-21 12:24:24 -03:00
else if ( ( evs [ * pos ] . delta . tv_nsec > MIN_BIT0_TIME ) & &
( evs [ * pos ] . delta . tv_nsec < MAX_BIT0_TIME ) )
2010-03-20 20:59:44 -03:00
bit = 0 ;
else
goto err ;
if ( bit ) {
int shift = count ;
/* Address first, then command */
if ( shift < 8 ) {
shift + = 8 ;
ircode | = 1 < < shift ;
} else if ( shift < 16 ) {
not_code | = 1 < < shift ;
} else if ( shift < 24 ) {
shift - = 16 ;
ircode | = 1 < < shift ;
} else {
shift - = 24 ;
not_code | = 1 < < shift ;
}
}
if ( + + count = = 32 )
break ;
}
/*
* Fixme : may need to accept Extended NEC protocol ?
*/
if ( ( ircode & ~ not_code ) ! = ircode ) {
IR_dprintk ( 1 , " NEC checksum error: code 0x%04x, not-code 0x%04x \n " ,
ircode , not_code ) ;
return - EINVAL ;
}
IR_dprintk ( 1 , " NEC scancode 0x%04x \n " , ircode ) ;
2010-03-21 12:24:24 -03:00
ir_keydown ( input_dev , ircode ) ;
ir_keyup ( input_dev ) ;
2010-03-20 20:59:44 -03:00
return ircode ;
err :
IR_dprintk ( 1 , " NEC decoded failed at bit %d while decoding %luus time \n " ,
2010-03-21 12:24:24 -03:00
count , ( evs [ * pos ] . delta . tv_nsec + 500 ) / 1000 ) ;
2010-03-20 20:59:44 -03:00
return - EINVAL ;
}
2010-03-21 12:24:24 -03:00
/**
* __ir_nec_decode ( ) - Decodes all NEC pulsecodes on a given array
* @ input_dev : the struct input_dev descriptor of the device
* @ evs : event array with type / duration of pulse / space
* @ len : length of the array
* This function returns the number of decoded pulses or - EINVAL if no
* pulse got decoded
*/
int ir_nec_decode ( struct input_dev * input_dev ,
struct ir_raw_event * evs ,
int len )
{
int pos = 0 ;
int rc = 0 ;
while ( pos < len ) {
if ( __ir_nec_decode ( input_dev , evs , len , & pos ) > = 0 )
rc + + ;
}
if ( ! rc )
return - EINVAL ;
return rc ;
}
2010-03-20 20:59:44 -03:00
EXPORT_SYMBOL_GPL ( ir_nec_decode ) ;