2012-11-12 15:42:59 +01:00
/*
* HID over I2C protocol implementation
*
* Copyright ( c ) 2012 Benjamin Tissoires < benjamin . tissoires @ gmail . com >
* Copyright ( c ) 2012 Ecole Nationale de l ' Aviation Civile , France
* Copyright ( c ) 2012 Red Hat , Inc
*
* This code is partly based on " USB HID support for Linux " :
*
* Copyright ( c ) 1999 Andreas Gal
* Copyright ( c ) 2000 - 2005 Vojtech Pavlik < vojtech @ suse . cz >
* Copyright ( c ) 2005 Michael Haboustak < mike - @ cinci . rr . com > for Concept2 , Inc
* Copyright ( c ) 2007 - 2008 Oliver Neukum
* Copyright ( c ) 2006 - 2010 Jiri Kosina
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive for
* more details .
*/
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/input.h>
# include <linux/delay.h>
# include <linux/slab.h>
# include <linux/pm.h>
# include <linux/device.h>
# include <linux/wait.h>
# include <linux/err.h>
# include <linux/string.h>
# include <linux/list.h>
# include <linux/jiffies.h>
# include <linux/kernel.h>
# include <linux/hid.h>
2012-12-12 18:00:02 +01:00
# include <linux/mutex.h>
2013-01-09 16:43:08 +02:00
# include <linux/acpi.h>
2012-11-12 15:42:59 +01:00
# include <linux/i2c/i2c-hid.h>
/* flags */
# define I2C_HID_STARTED (1 << 0)
# define I2C_HID_RESET_PENDING (1 << 1)
# define I2C_HID_READ_PENDING (1 << 2)
# define I2C_HID_PWR_ON 0x00
# define I2C_HID_PWR_SLEEP 0x01
/* debug option */
2012-12-04 16:27:45 +01:00
static bool debug ;
2012-11-12 15:42:59 +01:00
module_param ( debug , bool , 0444 ) ;
MODULE_PARM_DESC ( debug , " print a lot of debug information " ) ;
2012-12-04 16:27:46 +01:00
# define i2c_hid_dbg(ihid, fmt, arg...) \
do { \
if ( debug ) \
dev_printk ( KERN_DEBUG , & ( ihid ) - > client - > dev , fmt , # # arg ) ; \
} while ( 0 )
2012-11-12 15:42:59 +01:00
struct i2c_hid_desc {
__le16 wHIDDescLength ;
__le16 bcdVersion ;
__le16 wReportDescLength ;
__le16 wReportDescRegister ;
__le16 wInputRegister ;
__le16 wMaxInputLength ;
__le16 wOutputRegister ;
__le16 wMaxOutputLength ;
__le16 wCommandRegister ;
__le16 wDataRegister ;
__le16 wVendorID ;
__le16 wProductID ;
__le16 wVersionID ;
2012-12-05 15:02:53 +01:00
__le32 reserved ;
2012-11-12 15:42:59 +01:00
} __packed ;
struct i2c_hid_cmd {
unsigned int registerIndex ;
__u8 opcode ;
unsigned int length ;
bool wait ;
} ;
union command {
u8 data [ 0 ] ;
struct cmd {
__le16 reg ;
__u8 reportTypeID ;
__u8 opcode ;
} __packed c ;
} ;
# define I2C_HID_CMD(opcode_) \
. opcode = opcode_ , . length = 4 , \
. registerIndex = offsetof ( struct i2c_hid_desc , wCommandRegister )
/* fetch HID descriptor */
static const struct i2c_hid_cmd hid_descr_cmd = { . length = 2 } ;
/* fetch report descriptors */
static const struct i2c_hid_cmd hid_report_descr_cmd = {
. registerIndex = offsetof ( struct i2c_hid_desc ,
wReportDescRegister ) ,
. opcode = 0x00 ,
. length = 2 } ;
/* commands */
static const struct i2c_hid_cmd hid_reset_cmd = { I2C_HID_CMD ( 0x01 ) ,
. wait = true } ;
static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD ( 0x02 ) } ;
static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD ( 0x03 ) } ;
static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD ( 0x08 ) } ;
2013-06-17 16:15:06 -07:00
static const struct i2c_hid_cmd hid_no_cmd = { . length = 0 } ;
2012-12-04 16:27:47 +01:00
/*
* These definitions are not used here , but are defined by the spec .
* Keeping them here for documentation purposes .
*
* static const struct i2c_hid_cmd hid_get_idle_cmd = { I2C_HID_CMD ( 0x04 ) } ;
* static const struct i2c_hid_cmd hid_set_idle_cmd = { I2C_HID_CMD ( 0x05 ) } ;
* static const struct i2c_hid_cmd hid_get_protocol_cmd = { I2C_HID_CMD ( 0x06 ) } ;
* static const struct i2c_hid_cmd hid_set_protocol_cmd = { I2C_HID_CMD ( 0x07 ) } ;
*/
2012-11-12 15:42:59 +01:00
2012-12-12 18:00:02 +01:00
static DEFINE_MUTEX ( i2c_hid_open_mut ) ;
2012-11-12 15:42:59 +01:00
/* The main device structure */
struct i2c_hid {
struct i2c_client * client ; /* i2c client */
struct hid_device * hid ; /* pointer to corresponding HID dev */
union {
__u8 hdesc_buffer [ sizeof ( struct i2c_hid_desc ) ] ;
struct i2c_hid_desc hdesc ; /* the HID Descriptor */
} ;
__le16 wHIDDescRegister ; /* location of the i2c
* register of the HID
* descriptor . */
unsigned int bufsize ; /* i2c buffer size */
char * inbuf ; /* Input buffer */
char * cmdbuf ; /* Command buffer */
char * argsbuf ; /* Command arguments buffer */
unsigned long flags ; /* device flags */
wait_queue_head_t wait ; /* For waiting the interrupt */
2013-01-09 16:43:08 +02:00
struct i2c_hid_platform_data pdata ;
2012-11-12 15:42:59 +01:00
} ;
static int __i2c_hid_command ( struct i2c_client * client ,
const struct i2c_hid_cmd * command , u8 reportID ,
u8 reportType , u8 * args , int args_len ,
unsigned char * buf_recv , int data_len )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
union command * cmd = ( union command * ) ihid - > cmdbuf ;
int ret ;
struct i2c_msg msg [ 2 ] ;
int msg_num = 1 ;
int length = command - > length ;
bool wait = command - > wait ;
unsigned int registerIndex = command - > registerIndex ;
/* special case for hid_descr_cmd */
if ( command = = & hid_descr_cmd ) {
cmd - > c . reg = ihid - > wHIDDescRegister ;
} else {
cmd - > data [ 0 ] = ihid - > hdesc_buffer [ registerIndex ] ;
cmd - > data [ 1 ] = ihid - > hdesc_buffer [ registerIndex + 1 ] ;
}
if ( length > 2 ) {
cmd - > c . opcode = command - > opcode ;
cmd - > c . reportTypeID = reportID | reportType < < 4 ;
}
memcpy ( cmd - > data + length , args , args_len ) ;
length + = args_len ;
i2c_hid_dbg ( ihid , " %s: cmd=%*ph \n " , __func__ , length , cmd - > data ) ;
msg [ 0 ] . addr = client - > addr ;
msg [ 0 ] . flags = client - > flags & I2C_M_TEN ;
msg [ 0 ] . len = length ;
msg [ 0 ] . buf = cmd - > data ;
if ( data_len > 0 ) {
msg [ 1 ] . addr = client - > addr ;
msg [ 1 ] . flags = client - > flags & I2C_M_TEN ;
msg [ 1 ] . flags | = I2C_M_RD ;
msg [ 1 ] . len = data_len ;
msg [ 1 ] . buf = buf_recv ;
msg_num = 2 ;
set_bit ( I2C_HID_READ_PENDING , & ihid - > flags ) ;
}
if ( wait )
set_bit ( I2C_HID_RESET_PENDING , & ihid - > flags ) ;
ret = i2c_transfer ( client - > adapter , msg , msg_num ) ;
if ( data_len > 0 )
clear_bit ( I2C_HID_READ_PENDING , & ihid - > flags ) ;
if ( ret ! = msg_num )
return ret < 0 ? ret : - EIO ;
ret = 0 ;
if ( wait ) {
i2c_hid_dbg ( ihid , " %s: waiting... \n " , __func__ ) ;
if ( ! wait_event_timeout ( ihid - > wait ,
! test_bit ( I2C_HID_RESET_PENDING , & ihid - > flags ) ,
msecs_to_jiffies ( 5000 ) ) )
ret = - ENODATA ;
i2c_hid_dbg ( ihid , " %s: finished. \n " , __func__ ) ;
}
return ret ;
}
static int i2c_hid_command ( struct i2c_client * client ,
const struct i2c_hid_cmd * command ,
unsigned char * buf_recv , int data_len )
{
return __i2c_hid_command ( client , command , 0 , 0 , NULL , 0 ,
buf_recv , data_len ) ;
}
static int i2c_hid_get_report ( struct i2c_client * client , u8 reportType ,
u8 reportID , unsigned char * buf_recv , int data_len )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
u8 args [ 3 ] ;
int ret ;
int args_len = 0 ;
u16 readRegister = le16_to_cpu ( ihid - > hdesc . wDataRegister ) ;
i2c_hid_dbg ( ihid , " %s \n " , __func__ ) ;
if ( reportID > = 0x0F ) {
args [ args_len + + ] = reportID ;
reportID = 0x0F ;
}
args [ args_len + + ] = readRegister & 0xFF ;
args [ args_len + + ] = readRegister > > 8 ;
ret = __i2c_hid_command ( client , & hid_get_report_cmd , reportID ,
reportType , args , args_len , buf_recv , data_len ) ;
if ( ret ) {
dev_err ( & client - > dev ,
" failed to retrieve report from device. \n " ) ;
2012-12-04 16:27:48 +01:00
return ret ;
2012-11-12 15:42:59 +01:00
}
return 0 ;
}
static int i2c_hid_set_report ( struct i2c_client * client , u8 reportType ,
u8 reportID , unsigned char * buf , size_t data_len )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
u8 * args = ihid - > argsbuf ;
2013-06-17 16:15:06 -07:00
const struct i2c_hid_cmd * hidcmd = & hid_set_report_cmd ;
2012-11-12 15:42:59 +01:00
int ret ;
u16 dataRegister = le16_to_cpu ( ihid - > hdesc . wDataRegister ) ;
2013-06-17 16:15:06 -07:00
u16 outputRegister = le16_to_cpu ( ihid - > hdesc . wOutputRegister ) ;
u16 maxOutputLength = le16_to_cpu ( ihid - > hdesc . wMaxOutputLength ) ;
2012-11-12 15:42:59 +01:00
/* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
u16 size = 2 /* size */ +
( reportID ? 1 : 0 ) /* reportID */ +
data_len /* buf */ ;
int args_len = ( reportID > = 0x0F ? 1 : 0 ) /* optional third byte */ +
2 /* dataRegister */ +
size /* args */ ;
int index = 0 ;
i2c_hid_dbg ( ihid , " %s \n " , __func__ ) ;
if ( reportID > = 0x0F ) {
args [ index + + ] = reportID ;
reportID = 0x0F ;
}
2013-06-17 16:15:06 -07:00
/*
* use the data register for feature reports or if the device does not
* support the output register
*/
if ( reportType = = 0x03 | | maxOutputLength = = 0 ) {
args [ index + + ] = dataRegister & 0xFF ;
args [ index + + ] = dataRegister > > 8 ;
} else {
args [ index + + ] = outputRegister & 0xFF ;
args [ index + + ] = outputRegister > > 8 ;
hidcmd = & hid_no_cmd ;
}
2012-11-12 15:42:59 +01:00
args [ index + + ] = size & 0xFF ;
args [ index + + ] = size > > 8 ;
if ( reportID )
args [ index + + ] = reportID ;
memcpy ( & args [ index ] , buf , data_len ) ;
2013-06-17 16:15:06 -07:00
ret = __i2c_hid_command ( client , hidcmd , reportID ,
2012-11-12 15:42:59 +01:00
reportType , args , args_len , NULL , 0 ) ;
if ( ret ) {
dev_err ( & client - > dev , " failed to set a report to device. \n " ) ;
2012-12-04 16:27:48 +01:00
return ret ;
2012-11-12 15:42:59 +01:00
}
return data_len ;
}
static int i2c_hid_set_power ( struct i2c_client * client , int power_state )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
int ret ;
i2c_hid_dbg ( ihid , " %s \n " , __func__ ) ;
ret = __i2c_hid_command ( client , & hid_set_power_cmd , power_state ,
0 , NULL , 0 , NULL , 0 ) ;
if ( ret )
dev_err ( & client - > dev , " failed to change power setting. \n " ) ;
return ret ;
}
static int i2c_hid_hwreset ( struct i2c_client * client )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
int ret ;
i2c_hid_dbg ( ihid , " %s \n " , __func__ ) ;
ret = i2c_hid_set_power ( client , I2C_HID_PWR_ON ) ;
if ( ret )
return ret ;
i2c_hid_dbg ( ihid , " resetting... \n " ) ;
ret = i2c_hid_command ( client , & hid_reset_cmd , NULL , 0 ) ;
if ( ret ) {
dev_err ( & client - > dev , " failed to reset device. \n " ) ;
i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
return ret ;
}
return 0 ;
}
2012-12-04 16:27:48 +01:00
static void i2c_hid_get_input ( struct i2c_hid * ihid )
2012-11-12 15:42:59 +01:00
{
int ret , ret_size ;
int size = le16_to_cpu ( ihid - > hdesc . wMaxInputLength ) ;
ret = i2c_master_recv ( ihid - > client , ihid - > inbuf , size ) ;
if ( ret ! = size ) {
if ( ret < 0 )
2012-12-04 16:27:48 +01:00
return ;
2012-11-12 15:42:59 +01:00
dev_err ( & ihid - > client - > dev , " %s: got %d data instead of %d \n " ,
__func__ , ret , size ) ;
2012-12-04 16:27:48 +01:00
return ;
2012-11-12 15:42:59 +01:00
}
ret_size = ihid - > inbuf [ 0 ] | ihid - > inbuf [ 1 ] < < 8 ;
if ( ! ret_size ) {
/* host or device initiated RESET completed */
if ( test_and_clear_bit ( I2C_HID_RESET_PENDING , & ihid - > flags ) )
wake_up ( & ihid - > wait ) ;
2012-12-04 16:27:48 +01:00
return ;
2012-11-12 15:42:59 +01:00
}
if ( ret_size > size ) {
dev_err ( & ihid - > client - > dev , " %s: incomplete report (%d/%d) \n " ,
__func__ , size , ret_size ) ;
2012-12-04 16:27:48 +01:00
return ;
2012-11-12 15:42:59 +01:00
}
i2c_hid_dbg ( ihid , " input: %*ph \n " , ret_size , ihid - > inbuf ) ;
if ( test_bit ( I2C_HID_STARTED , & ihid - > flags ) )
hid_input_report ( ihid - > hid , HID_INPUT_REPORT , ihid - > inbuf + 2 ,
ret_size - 2 , 1 ) ;
2012-12-04 16:27:48 +01:00
return ;
2012-11-12 15:42:59 +01:00
}
static irqreturn_t i2c_hid_irq ( int irq , void * dev_id )
{
struct i2c_hid * ihid = dev_id ;
if ( test_bit ( I2C_HID_READ_PENDING , & ihid - > flags ) )
return IRQ_HANDLED ;
i2c_hid_get_input ( ihid ) ;
return IRQ_HANDLED ;
}
static int i2c_hid_get_report_length ( struct hid_report * report )
{
return ( ( report - > size - 1 ) > > 3 ) + 1 +
report - > device - > report_enum [ report - > type ] . numbered + 2 ;
}
static void i2c_hid_init_report ( struct hid_report * report , u8 * buffer ,
size_t bufsize )
{
struct hid_device * hid = report - > device ;
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
unsigned int size , ret_size ;
size = i2c_hid_get_report_length ( report ) ;
2012-12-04 16:27:50 +01:00
if ( i2c_hid_get_report ( client ,
2012-11-12 15:42:59 +01:00
report - > type = = HID_FEATURE_REPORT ? 0x03 : 0x01 ,
2012-12-04 16:27:50 +01:00
report - > id , buffer , size ) )
return ;
2012-11-12 15:42:59 +01:00
i2c_hid_dbg ( ihid , " report (len=%d): %*ph \n " , size , size , ihid - > inbuf ) ;
ret_size = buffer [ 0 ] | ( buffer [ 1 ] < < 8 ) ;
if ( ret_size ! = size ) {
dev_err ( & client - > dev , " error in %s size:%d / ret_size:%d \n " ,
__func__ , size , ret_size ) ;
return ;
}
/* hid->driver_lock is held as we are in probe function,
* we just need to setup the input fields , so using
* hid_report_raw_event is safe . */
hid_report_raw_event ( hid , report - > type , buffer + 2 , size - 2 , 1 ) ;
}
/*
* Initialize all reports
*/
static void i2c_hid_init_reports ( struct hid_device * hid )
{
struct hid_report * report ;
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
u8 * inbuf = kzalloc ( ihid - > bufsize , GFP_KERNEL ) ;
2012-12-04 16:27:48 +01:00
if ( ! inbuf ) {
dev_err ( & client - > dev , " can not retrieve initial reports \n " ) ;
2012-11-12 15:42:59 +01:00
return ;
2012-12-04 16:27:48 +01:00
}
2012-11-12 15:42:59 +01:00
list_for_each_entry ( report ,
& hid - > report_enum [ HID_INPUT_REPORT ] . report_list , list )
i2c_hid_init_report ( report , inbuf , ihid - > bufsize ) ;
list_for_each_entry ( report ,
& hid - > report_enum [ HID_FEATURE_REPORT ] . report_list , list )
i2c_hid_init_report ( report , inbuf , ihid - > bufsize ) ;
kfree ( inbuf ) ;
}
/*
* Traverse the supplied list of reports and find the longest
*/
static void i2c_hid_find_max_report ( struct hid_device * hid , unsigned int type ,
unsigned int * max )
{
struct hid_report * report ;
unsigned int size ;
/* We should not rely on wMaxInputLength, as some devices may set it to
* a wrong length . */
list_for_each_entry ( report , & hid - > report_enum [ type ] . report_list , list ) {
size = i2c_hid_get_report_length ( report ) ;
if ( * max < size )
* max = size ;
}
}
2012-12-05 15:02:54 +01:00
static void i2c_hid_free_buffers ( struct i2c_hid * ihid )
{
kfree ( ihid - > inbuf ) ;
kfree ( ihid - > argsbuf ) ;
kfree ( ihid - > cmdbuf ) ;
ihid - > inbuf = NULL ;
ihid - > cmdbuf = NULL ;
ihid - > argsbuf = NULL ;
ihid - > bufsize = 0 ;
}
static int i2c_hid_alloc_buffers ( struct i2c_hid * ihid , size_t report_size )
2012-11-12 15:42:59 +01:00
{
/* the worst case is computed from the set_report command with a
* reportID > 15 and the maximum report length */
int args_len = sizeof ( __u8 ) + /* optional ReportID byte */
sizeof ( __u16 ) + /* data register */
sizeof ( __u16 ) + /* size of the report */
2012-12-05 15:02:54 +01:00
report_size ; /* report */
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:54 +01:00
ihid - > inbuf = kzalloc ( report_size , GFP_KERNEL ) ;
2012-11-12 15:42:59 +01:00
ihid - > argsbuf = kzalloc ( args_len , GFP_KERNEL ) ;
ihid - > cmdbuf = kzalloc ( sizeof ( union command ) + args_len , GFP_KERNEL ) ;
2012-12-05 15:02:54 +01:00
if ( ! ihid - > inbuf | | ! ihid - > argsbuf | | ! ihid - > cmdbuf ) {
i2c_hid_free_buffers ( ihid ) ;
2012-11-12 15:42:59 +01:00
return - ENOMEM ;
}
2012-12-05 15:02:54 +01:00
ihid - > bufsize = report_size ;
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:54 +01:00
return 0 ;
2012-11-12 15:42:59 +01:00
}
static int i2c_hid_get_raw_report ( struct hid_device * hid ,
unsigned char report_number , __u8 * buf , size_t count ,
unsigned char report_type )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
2012-12-05 15:02:56 +01:00
size_t ret_count , ask_count ;
2012-11-12 15:42:59 +01:00
int ret ;
if ( report_type = = HID_OUTPUT_REPORT )
return - EINVAL ;
2012-12-05 15:02:56 +01:00
/* +2 bytes to include the size of the reply in the query buffer */
ask_count = min ( count + 2 , ( size_t ) ihid - > bufsize ) ;
2012-11-12 15:42:59 +01:00
ret = i2c_hid_get_report ( client ,
report_type = = HID_FEATURE_REPORT ? 0x03 : 0x01 ,
2012-12-05 15:02:56 +01:00
report_number , ihid - > inbuf , ask_count ) ;
2012-11-12 15:42:59 +01:00
if ( ret < 0 )
return ret ;
2012-12-05 15:02:56 +01:00
ret_count = ihid - > inbuf [ 0 ] | ( ihid - > inbuf [ 1 ] < < 8 ) ;
2012-11-12 15:42:59 +01:00
2012-12-06 10:59:28 +01:00
if ( ret_count < = 2 )
2012-12-05 15:02:56 +01:00
return 0 ;
ret_count = min ( ret_count , ask_count ) ;
/* The query buffer contains the size, dropping it in the reply */
count = min ( count , ret_count - 2 ) ;
2012-11-12 15:42:59 +01:00
memcpy ( buf , ihid - > inbuf + 2 , count ) ;
return count ;
}
static int i2c_hid_output_raw_report ( struct hid_device * hid , __u8 * buf ,
size_t count , unsigned char report_type )
{
struct i2c_client * client = hid - > driver_data ;
int report_id = buf [ 0 ] ;
2013-01-31 17:50:02 +01:00
int ret ;
2012-11-12 15:42:59 +01:00
if ( report_type = = HID_INPUT_REPORT )
return - EINVAL ;
2013-01-31 17:50:02 +01:00
if ( report_id ) {
buf + + ;
count - - ;
}
ret = i2c_hid_set_report ( client ,
2012-11-12 15:42:59 +01:00
report_type = = HID_FEATURE_REPORT ? 0x03 : 0x02 ,
report_id , buf , count ) ;
2013-01-31 17:50:02 +01:00
if ( report_id & & ret > = 0 )
ret + + ; /* add report_id to the number of transfered bytes */
return ret ;
2012-11-12 15:42:59 +01:00
}
2013-02-25 11:31:50 +01:00
static void i2c_hid_request ( struct hid_device * hid , struct hid_report * rep ,
int reqtype )
{
struct i2c_client * client = hid - > driver_data ;
char * buf ;
int ret ;
2013-04-03 05:45:21 -07:00
int len = i2c_hid_get_report_length ( rep ) - 2 ;
2013-02-25 11:31:50 +01:00
2013-04-03 05:45:21 -07:00
buf = kzalloc ( len , GFP_KERNEL ) ;
2013-02-25 11:31:50 +01:00
if ( ! buf )
return ;
switch ( reqtype ) {
case HID_REQ_GET_REPORT :
2013-04-03 05:45:21 -07:00
ret = i2c_hid_get_raw_report ( hid , rep - > id , buf , len , rep - > type ) ;
2013-02-25 11:31:50 +01:00
if ( ret < 0 )
dev_err ( & client - > dev , " %s: unable to get report: %d \n " ,
__func__ , ret ) ;
else
hid_input_report ( hid , rep - > type , buf , ret , 0 ) ;
break ;
case HID_REQ_SET_REPORT :
hid_output_report ( rep , buf ) ;
2013-04-03 05:45:21 -07:00
i2c_hid_output_raw_report ( hid , buf , len , rep - > type ) ;
2013-02-25 11:31:50 +01:00
break ;
}
kfree ( buf ) ;
}
2012-11-12 15:42:59 +01:00
static int i2c_hid_parse ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
struct i2c_hid_desc * hdesc = & ihid - > hdesc ;
unsigned int rsize ;
char * rdesc ;
int ret ;
int tries = 3 ;
i2c_hid_dbg ( ihid , " entering %s \n " , __func__ ) ;
rsize = le16_to_cpu ( hdesc - > wReportDescLength ) ;
if ( ! rsize | | rsize > HID_MAX_DESCRIPTOR_SIZE ) {
dbg_hid ( " weird size of report descriptor (%u) \n " , rsize ) ;
return - EINVAL ;
}
do {
ret = i2c_hid_hwreset ( client ) ;
if ( ret )
msleep ( 1000 ) ;
} while ( tries - - > 0 & & ret ) ;
if ( ret )
return ret ;
rdesc = kzalloc ( rsize , GFP_KERNEL ) ;
if ( ! rdesc ) {
dbg_hid ( " couldn't allocate rdesc memory \n " ) ;
return - ENOMEM ;
}
i2c_hid_dbg ( ihid , " asking HID report descriptor \n " ) ;
ret = i2c_hid_command ( client , & hid_report_descr_cmd , rdesc , rsize ) ;
if ( ret ) {
hid_err ( hid , " reading report descriptor failed \n " ) ;
kfree ( rdesc ) ;
return - EIO ;
}
i2c_hid_dbg ( ihid , " Report Descriptor: %*ph \n " , rsize , rdesc ) ;
ret = hid_parse_report ( hid , rdesc , rsize ) ;
kfree ( rdesc ) ;
if ( ret ) {
dbg_hid ( " parsing report descriptor failed \n " ) ;
return ret ;
}
return 0 ;
}
static int i2c_hid_start ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
int ret ;
2012-12-05 15:02:54 +01:00
unsigned int bufsize = HID_MIN_BUFFER_SIZE ;
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:54 +01:00
i2c_hid_find_max_report ( hid , HID_INPUT_REPORT , & bufsize ) ;
i2c_hid_find_max_report ( hid , HID_OUTPUT_REPORT , & bufsize ) ;
i2c_hid_find_max_report ( hid , HID_FEATURE_REPORT , & bufsize ) ;
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:54 +01:00
if ( bufsize > ihid - > bufsize ) {
2012-11-12 15:42:59 +01:00
i2c_hid_free_buffers ( ihid ) ;
2012-12-05 15:02:54 +01:00
ret = i2c_hid_alloc_buffers ( ihid , bufsize ) ;
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:54 +01:00
if ( ret )
2012-11-12 15:42:59 +01:00
return ret ;
}
if ( ! ( hid - > quirks & HID_QUIRK_NO_INIT_REPORTS ) )
i2c_hid_init_reports ( hid ) ;
return 0 ;
}
static void i2c_hid_stop ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
hid - > claimed = 0 ;
i2c_hid_free_buffers ( ihid ) ;
}
static int i2c_hid_open ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
2012-12-12 18:00:02 +01:00
int ret = 0 ;
2012-11-12 15:42:59 +01:00
2012-12-12 18:00:02 +01:00
mutex_lock ( & i2c_hid_open_mut ) ;
2012-11-12 15:42:59 +01:00
if ( ! hid - > open + + ) {
ret = i2c_hid_set_power ( client , I2C_HID_PWR_ON ) ;
if ( ret ) {
hid - > open - - ;
2012-12-12 18:00:02 +01:00
goto done ;
2012-11-12 15:42:59 +01:00
}
set_bit ( I2C_HID_STARTED , & ihid - > flags ) ;
}
2012-12-12 18:00:02 +01:00
done :
mutex_unlock ( & i2c_hid_open_mut ) ;
return ret ;
2012-11-12 15:42:59 +01:00
}
static void i2c_hid_close ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
/* protecting hid->open to make sure we don't restart
* data acquistion due to a resumption we no longer
* care about
*/
2012-12-12 18:00:02 +01:00
mutex_lock ( & i2c_hid_open_mut ) ;
2012-11-12 15:42:59 +01:00
if ( ! - - hid - > open ) {
clear_bit ( I2C_HID_STARTED , & ihid - > flags ) ;
/* Save some power */
i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
}
2012-12-12 18:00:02 +01:00
mutex_unlock ( & i2c_hid_open_mut ) ;
2012-11-12 15:42:59 +01:00
}
static int i2c_hid_power ( struct hid_device * hid , int lvl )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
int ret = 0 ;
i2c_hid_dbg ( ihid , " %s lvl:%d \n " , __func__ , lvl ) ;
switch ( lvl ) {
case PM_HINT_FULLON :
ret = i2c_hid_set_power ( client , I2C_HID_PWR_ON ) ;
break ;
case PM_HINT_NORMAL :
ret = i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
break ;
}
return ret ;
}
static int i2c_hid_hidinput_input_event ( struct input_dev * dev ,
unsigned int type , unsigned int code , int value )
{
struct hid_device * hid = input_get_drvdata ( dev ) ;
struct hid_field * field ;
int offset ;
if ( type = = EV_FF )
return input_ff_event ( dev , type , code , value ) ;
if ( type ! = EV_LED )
return - 1 ;
offset = hidinput_find_field ( hid , type , code , & field ) ;
if ( offset = = - 1 ) {
hid_warn ( dev , " event field not found \n " ) ;
return - 1 ;
}
2012-12-04 16:27:48 +01:00
return hid_set_field ( field , offset , value ) ;
2012-11-12 15:42:59 +01:00
}
static struct hid_ll_driver i2c_hid_ll_driver = {
. parse = i2c_hid_parse ,
. start = i2c_hid_start ,
. stop = i2c_hid_stop ,
. open = i2c_hid_open ,
. close = i2c_hid_close ,
. power = i2c_hid_power ,
2013-02-25 11:31:50 +01:00
. request = i2c_hid_request ,
2012-11-12 15:42:59 +01:00
. hidinput_input_event = i2c_hid_hidinput_input_event ,
} ;
2012-12-21 15:14:44 -08:00
static int i2c_hid_init_irq ( struct i2c_client * client )
2012-11-12 15:42:59 +01:00
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
int ret ;
dev_dbg ( & client - > dev , " Requesting IRQ: %d \n " , client - > irq ) ;
ret = request_threaded_irq ( client - > irq , NULL , i2c_hid_irq ,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
client - > name , ihid ) ;
if ( ret < 0 ) {
2012-12-04 16:27:49 +01:00
dev_warn ( & client - > dev ,
2012-11-12 15:42:59 +01:00
" Could not register for %s interrupt, irq = %d, "
" ret = %d \n " ,
2012-12-04 16:27:49 +01:00
client - > name , client - > irq , ret ) ;
2012-11-12 15:42:59 +01:00
return ret ;
}
return 0 ;
}
2012-12-21 15:14:44 -08:00
static int i2c_hid_fetch_hid_descriptor ( struct i2c_hid * ihid )
2012-11-12 15:42:59 +01:00
{
struct i2c_client * client = ihid - > client ;
struct i2c_hid_desc * hdesc = & ihid - > hdesc ;
unsigned int dsize ;
int ret ;
/* Fetch the length of HID description, retrieve the 4 first bytes:
* bytes 0 - 1 - > length
* bytes 2 - 3 - > bcdVersion ( has to be 1.00 ) */
ret = i2c_hid_command ( client , & hid_descr_cmd , ihid - > hdesc_buffer , 4 ) ;
i2c_hid_dbg ( ihid , " %s, ihid->hdesc_buffer: %*ph \n " ,
__func__ , 4 , ihid - > hdesc_buffer ) ;
if ( ret ) {
2012-12-04 16:27:49 +01:00
dev_err ( & client - > dev ,
" unable to fetch the size of HID descriptor (ret=%d) \n " ,
2012-11-12 15:42:59 +01:00
ret ) ;
return - ENODEV ;
}
dsize = le16_to_cpu ( hdesc - > wHIDDescLength ) ;
2012-12-05 15:02:53 +01:00
/*
* the size of the HID descriptor should at least contain
* its size and the bcdVersion ( 4 bytes ) , and should not be greater
* than sizeof ( struct i2c_hid_desc ) as we directly fill this struct
* through i2c_hid_command .
*/
if ( dsize < 4 | | dsize > sizeof ( struct i2c_hid_desc ) ) {
2012-11-12 15:42:59 +01:00
dev_err ( & client - > dev , " weird size of HID descriptor (%u) \n " ,
dsize ) ;
return - ENODEV ;
}
/* check bcdVersion == 1.0 */
if ( le16_to_cpu ( hdesc - > bcdVersion ) ! = 0x0100 ) {
dev_err ( & client - > dev ,
2012-12-04 16:27:49 +01:00
" unexpected HID descriptor bcdVersion (0x%04hx) \n " ,
2012-11-12 15:42:59 +01:00
le16_to_cpu ( hdesc - > bcdVersion ) ) ;
return - ENODEV ;
}
i2c_hid_dbg ( ihid , " Fetching the HID descriptor \n " ) ;
ret = i2c_hid_command ( client , & hid_descr_cmd , ihid - > hdesc_buffer ,
dsize ) ;
if ( ret ) {
dev_err ( & client - > dev , " hid_descr_cmd Fail \n " ) ;
return - ENODEV ;
}
i2c_hid_dbg ( ihid , " HID Descriptor: %*ph \n " , dsize , ihid - > hdesc_buffer ) ;
return 0 ;
}
2013-01-09 16:43:08 +02:00
# ifdef CONFIG_ACPI
static int i2c_hid_acpi_pdata ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
static u8 i2c_hid_guid [ ] = {
0xF7 , 0xF6 , 0xDF , 0x3C , 0x67 , 0x42 , 0x55 , 0x45 ,
0xAD , 0x05 , 0xB3 , 0x0A , 0x3D , 0x89 , 0x38 , 0xDE ,
} ;
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER , NULL } ;
union acpi_object params [ 4 ] , * obj ;
struct acpi_object_list input ;
struct acpi_device * adev ;
acpi_handle handle ;
handle = ACPI_HANDLE ( & client - > dev ) ;
if ( ! handle | | acpi_bus_get_device ( handle , & adev ) )
return - ENODEV ;
input . count = ARRAY_SIZE ( params ) ;
input . pointer = params ;
params [ 0 ] . type = ACPI_TYPE_BUFFER ;
params [ 0 ] . buffer . length = sizeof ( i2c_hid_guid ) ;
params [ 0 ] . buffer . pointer = i2c_hid_guid ;
params [ 1 ] . type = ACPI_TYPE_INTEGER ;
params [ 1 ] . integer . value = 1 ;
params [ 2 ] . type = ACPI_TYPE_INTEGER ;
params [ 2 ] . integer . value = 1 ; /* HID function */
2013-08-19 14:01:17 +03:00
params [ 3 ] . type = ACPI_TYPE_PACKAGE ;
params [ 3 ] . package . count = 0 ;
params [ 3 ] . package . elements = NULL ;
2013-01-09 16:43:08 +02:00
if ( ACPI_FAILURE ( acpi_evaluate_object ( handle , " _DSM " , & input , & buf ) ) ) {
dev_err ( & client - > dev , " device _DSM execution failed \n " ) ;
return - ENODEV ;
}
obj = ( union acpi_object * ) buf . pointer ;
if ( obj - > type ! = ACPI_TYPE_INTEGER ) {
dev_err ( & client - > dev , " device _DSM returned invalid type: %d \n " ,
obj - > type ) ;
kfree ( buf . pointer ) ;
return - EINVAL ;
}
pdata - > hid_descriptor_address = obj - > integer . value ;
kfree ( buf . pointer ) ;
return 0 ;
}
static const struct acpi_device_id i2c_hid_acpi_match [ ] = {
{ " ACPI0C50 " , 0 } ,
{ " PNP0C50 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( acpi , i2c_hid_acpi_match ) ;
# else
static inline int i2c_hid_acpi_pdata ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
return - ENODEV ;
}
# endif
2012-12-21 15:14:44 -08:00
static int i2c_hid_probe ( struct i2c_client * client ,
const struct i2c_device_id * dev_id )
2012-11-12 15:42:59 +01:00
{
int ret ;
struct i2c_hid * ihid ;
struct hid_device * hid ;
__u16 hidRegister ;
struct i2c_hid_platform_data * platform_data = client - > dev . platform_data ;
dbg_hid ( " HID probe called for i2c 0x%02x \n " , client - > addr ) ;
if ( ! client - > irq ) {
dev_err ( & client - > dev ,
" HID over i2c has not been provided an Int IRQ \n " ) ;
return - EINVAL ;
}
ihid = kzalloc ( sizeof ( struct i2c_hid ) , GFP_KERNEL ) ;
if ( ! ihid )
return - ENOMEM ;
2013-01-09 16:43:08 +02:00
if ( ! platform_data ) {
ret = i2c_hid_acpi_pdata ( client , & ihid - > pdata ) ;
if ( ret ) {
dev_err ( & client - > dev ,
" HID register address not provided \n " ) ;
goto err ;
}
} else {
ihid - > pdata = * platform_data ;
}
2012-11-12 15:42:59 +01:00
i2c_set_clientdata ( client , ihid ) ;
ihid - > client = client ;
2013-01-09 16:43:08 +02:00
hidRegister = ihid - > pdata . hid_descriptor_address ;
2012-11-12 15:42:59 +01:00
ihid - > wHIDDescRegister = cpu_to_le16 ( hidRegister ) ;
init_waitqueue_head ( & ihid - > wait ) ;
/* we need to allocate the command buffer without knowing the maximum
* size of the reports . Let ' s use HID_MIN_BUFFER_SIZE , then we do the
* real computation later . */
2012-12-05 15:02:54 +01:00
ret = i2c_hid_alloc_buffers ( ihid , HID_MIN_BUFFER_SIZE ) ;
if ( ret < 0 )
goto err ;
2012-11-12 15:42:59 +01:00
ret = i2c_hid_fetch_hid_descriptor ( ihid ) ;
if ( ret < 0 )
goto err ;
ret = i2c_hid_init_irq ( client ) ;
if ( ret < 0 )
goto err ;
hid = hid_allocate_device ( ) ;
if ( IS_ERR ( hid ) ) {
ret = PTR_ERR ( hid ) ;
2012-12-05 15:02:55 +01:00
goto err_irq ;
2012-11-12 15:42:59 +01:00
}
ihid - > hid = hid ;
hid - > driver_data = client ;
hid - > ll_driver = & i2c_hid_ll_driver ;
hid - > hid_get_raw_report = i2c_hid_get_raw_report ;
hid - > hid_output_raw_report = i2c_hid_output_raw_report ;
hid - > dev . parent = & client - > dev ;
2013-01-09 16:43:08 +02:00
ACPI_HANDLE_SET ( & hid - > dev , ACPI_HANDLE ( & client - > dev ) ) ;
2012-11-12 15:42:59 +01:00
hid - > bus = BUS_I2C ;
hid - > version = le16_to_cpu ( ihid - > hdesc . bcdVersion ) ;
hid - > vendor = le16_to_cpu ( ihid - > hdesc . wVendorID ) ;
hid - > product = le16_to_cpu ( ihid - > hdesc . wProductID ) ;
2012-12-04 16:27:49 +01:00
snprintf ( hid - > name , sizeof ( hid - > name ) , " %s %04hX:%04hX " ,
2012-11-12 15:42:59 +01:00
client - > name , hid - > vendor , hid - > product ) ;
ret = hid_add_device ( hid ) ;
if ( ret ) {
if ( ret ! = - ENODEV )
hid_err ( client , " can't add hid device: %d \n " , ret ) ;
goto err_mem_free ;
}
return 0 ;
err_mem_free :
hid_destroy_device ( hid ) ;
2012-12-05 15:02:55 +01:00
err_irq :
free_irq ( client - > irq , ihid ) ;
2012-11-12 15:42:59 +01:00
2012-12-05 15:02:55 +01:00
err :
2012-11-20 17:09:40 +01:00
i2c_hid_free_buffers ( ihid ) ;
2012-11-12 15:42:59 +01:00
kfree ( ihid ) ;
return ret ;
}
2012-12-21 15:14:44 -08:00
static int i2c_hid_remove ( struct i2c_client * client )
2012-11-12 15:42:59 +01:00
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
struct hid_device * hid ;
hid = ihid - > hid ;
hid_destroy_device ( hid ) ;
free_irq ( client - > irq , ihid ) ;
2012-12-04 16:27:54 +01:00
if ( ihid - > bufsize )
i2c_hid_free_buffers ( ihid ) ;
2012-11-12 15:42:59 +01:00
kfree ( ihid ) ;
return 0 ;
}
# ifdef CONFIG_PM_SLEEP
static int i2c_hid_suspend ( struct device * dev )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
if ( device_may_wakeup ( & client - > dev ) )
2012-12-05 15:02:55 +01:00
enable_irq_wake ( client - > irq ) ;
2012-11-12 15:42:59 +01:00
/* Save some power */
i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
return 0 ;
}
static int i2c_hid_resume ( struct device * dev )
{
int ret ;
struct i2c_client * client = to_i2c_client ( dev ) ;
ret = i2c_hid_hwreset ( client ) ;
if ( ret )
return ret ;
if ( device_may_wakeup ( & client - > dev ) )
disable_irq_wake ( client - > irq ) ;
return 0 ;
}
# endif
static SIMPLE_DEV_PM_OPS ( i2c_hid_pm , i2c_hid_suspend , i2c_hid_resume ) ;
static const struct i2c_device_id i2c_hid_id_table [ ] = {
2012-12-04 16:27:42 +01:00
{ " hid " , 0 } ,
2012-11-12 15:42:59 +01:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , i2c_hid_id_table ) ;
static struct i2c_driver i2c_hid_driver = {
. driver = {
. name = " i2c_hid " ,
. owner = THIS_MODULE ,
. pm = & i2c_hid_pm ,
2013-01-09 16:43:08 +02:00
. acpi_match_table = ACPI_PTR ( i2c_hid_acpi_match ) ,
2012-11-12 15:42:59 +01:00
} ,
. probe = i2c_hid_probe ,
2012-12-21 15:14:44 -08:00
. remove = i2c_hid_remove ,
2012-11-12 15:42:59 +01:00
. id_table = i2c_hid_id_table ,
} ;
module_i2c_driver ( i2c_hid_driver ) ;
MODULE_DESCRIPTION ( " HID over I2C core driver " ) ;
MODULE_AUTHOR ( " Benjamin Tissoires <benjamin.tissoires@gmail.com> " ) ;
MODULE_LICENSE ( " GPL " ) ;