2012-07-30 23:38:28 +04:00
/***************************************************************************
* Copyright ( C ) 2010 - 2012 by Bruno Prémont < bonbons @ linux - vserver . org > *
* *
* Based on Logitech G13 driver ( v0 .4 ) *
* Copyright ( C ) 2009 by Rick L . Vinyard , Jr . < rvinyard @ cs . nmsu . edu > *
* *
* 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 driver 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 software . If not see < http : //www.gnu.org/licenses/>. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/hid.h>
# include <linux/hid-debug.h>
# include <linux/input.h>
# include "hid-ids.h"
# include <linux/fb.h>
# include <linux/vmalloc.h>
# include <linux/backlight.h>
# include <linux/lcd.h>
# include <linux/leds.h>
# include <linux/seq_file.h>
# include <linux/debugfs.h>
# include <linux/completion.h>
# include <linux/uaccess.h>
# include <linux/module.h>
2012-08-19 21:32:54 +04:00
# include <media/rc-core.h>
2012-07-30 23:38:28 +04:00
# include "hid-picolcd.h"
int picolcd_raw_cir ( struct picolcd_data * data ,
struct hid_report * report , u8 * raw_data , int size )
{
2012-08-19 21:32:54 +04:00
unsigned long flags ;
int i , w , sz ;
DEFINE_IR_RAW_EVENT ( rawir ) ;
/* ignore if rc_dev is NULL or status is shunned */
spin_lock_irqsave ( & data - > lock , flags ) ;
2012-09-07 10:47:41 +04:00
if ( ! data - > rc_dev | | ( data - > status & PICOLCD_CIR_SHUN ) ) {
2012-08-19 21:32:54 +04:00
spin_unlock_irqrestore ( & data - > lock , flags ) ;
return 1 ;
}
spin_unlock_irqrestore ( & data - > lock , flags ) ;
/* PicoLCD USB packets contain 16-bit intervals in network order,
* with value negated for pulse . Intervals are in microseconds .
*
* Note : some userspace LIRC code for PicoLCD says negated values
* for space - is it a matter of IR chip ? ( pulse for my TSOP2236 )
*
* In addition , the first interval seems to be around 15000 + base
* interval for non - first report of IR data - thus the quirk below
* to get RC_CODE to understand Sony and JVC remotes I have at hand
*/
sz = size > 0 ? min ( ( int ) raw_data [ 0 ] , size - 1 ) : 0 ;
for ( i = 0 ; i + 1 < sz ; i + = 2 ) {
init_ir_raw_event ( & rawir ) ;
w = ( raw_data [ i ] < < 8 ) | ( raw_data [ i + 1 ] ) ;
rawir . pulse = ! ! ( w & 0x8000 ) ;
rawir . duration = US_TO_NS ( rawir . pulse ? ( 65536 - w ) : w ) ;
/* Quirk!! - see above */
if ( i = = 0 & & rawir . duration > 15000000 )
rawir . duration - = 15000000 ;
ir_raw_event_store ( data - > rc_dev , & rawir ) ;
}
ir_raw_event_handle ( data - > rc_dev ) ;
2012-07-30 23:38:28 +04:00
return 1 ;
}
2012-08-19 21:32:54 +04:00
static int picolcd_cir_open ( struct rc_dev * dev )
{
struct picolcd_data * data = dev - > priv ;
unsigned long flags ;
spin_lock_irqsave ( & data - > lock , flags ) ;
data - > status & = ~ PICOLCD_CIR_SHUN ;
spin_unlock_irqrestore ( & data - > lock , flags ) ;
return 0 ;
}
static void picolcd_cir_close ( struct rc_dev * dev )
{
struct picolcd_data * data = dev - > priv ;
unsigned long flags ;
spin_lock_irqsave ( & data - > lock , flags ) ;
data - > status | = PICOLCD_CIR_SHUN ;
spin_unlock_irqrestore ( & data - > lock , flags ) ;
}
2012-07-30 23:38:28 +04:00
/* initialize CIR input device */
int picolcd_init_cir ( struct picolcd_data * data , struct hid_report * report )
{
2012-08-19 21:32:54 +04:00
struct rc_dev * rdev ;
int ret = 0 ;
rdev = rc_allocate_device ( ) ;
if ( ! rdev )
return - ENOMEM ;
rdev - > priv = data ;
rdev - > driver_type = RC_DRIVER_IR_RAW ;
2012-10-31 11:22:08 +04:00
rdev - > allowed_protos = RC_BIT_ALL ;
2012-08-19 21:32:54 +04:00
rdev - > open = picolcd_cir_open ;
rdev - > close = picolcd_cir_close ;
rdev - > input_name = data - > hdev - > name ;
rdev - > input_phys = data - > hdev - > phys ;
rdev - > input_id . bustype = data - > hdev - > bus ;
rdev - > input_id . vendor = data - > hdev - > vendor ;
rdev - > input_id . product = data - > hdev - > product ;
rdev - > input_id . version = data - > hdev - > version ;
rdev - > dev . parent = & data - > hdev - > dev ;
rdev - > driver_name = PICOLCD_NAME ;
rdev - > map_name = RC_MAP_RC6_MCE ;
rdev - > timeout = MS_TO_NS ( 100 ) ;
rdev - > rx_resolution = US_TO_NS ( 1 ) ;
ret = rc_register_device ( rdev ) ;
if ( ret )
goto err ;
data - > rc_dev = rdev ;
2012-07-30 23:38:28 +04:00
return 0 ;
2012-08-19 21:32:54 +04:00
err :
rc_free_device ( rdev ) ;
return ret ;
2012-07-30 23:38:28 +04:00
}
void picolcd_exit_cir ( struct picolcd_data * data )
{
2012-08-19 21:32:54 +04:00
struct rc_dev * rdev = data - > rc_dev ;
data - > rc_dev = NULL ;
2013-08-31 16:07:48 +04:00
if ( rdev )
rc_unregister_device ( rdev ) ;
2012-07-30 23:38:28 +04:00
}