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>
2016-11-21 15:21:27 +01:00
# include <linux/irq.h>
2012-11-12 15:42:59 +01:00
# 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>
2013-06-13 09:50:35 +02:00
# include <linux/of.h>
2016-12-09 13:37:07 +01:00
# include <linux/regulator/consumer.h>
2012-11-12 15:42:59 +01:00
2017-05-21 22:30:33 +02:00
# include <linux/platform_data/i2c-hid.h>
2012-11-12 15:42:59 +01:00
2016-11-10 11:47:13 +08:00
# include "../hid-ids.h"
2018-09-19 11:46:23 +02:00
# include "i2c-hid.h"
2016-11-10 11:47:13 +08:00
/* quirks to control the device */
# define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0)
2017-11-07 13:28:00 +01:00
# define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1)
2019-01-07 15:24:29 +08:00
# define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
2016-11-10 11:47:13 +08:00
2012-11-12 15:42:59 +01:00
/* flags */
2015-05-14 11:33:30 +03:00
# define I2C_HID_STARTED 0
# define I2C_HID_RESET_PENDING 1
# define I2C_HID_READ_PENDING 2
2012-11-12 15:42:59 +01:00
# 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
/* 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 */
2018-01-08 10:41:40 +08:00
u8 * inbuf ; /* Input buffer */
u8 * rawbuf ; /* Raw Input buffer */
u8 * cmdbuf ; /* Command buffer */
u8 * argsbuf ; /* Command arguments buffer */
2012-11-12 15:42:59 +01:00
unsigned long flags ; /* device flags */
2016-11-10 11:47:13 +08:00
unsigned long quirks ; /* Various quirks */
2012-11-12 15:42:59 +01:00
wait_queue_head_t wait ; /* For waiting the interrupt */
2013-01-09 16:43:08 +02:00
struct i2c_hid_platform_data pdata ;
2015-07-30 14:49:00 -07:00
bool irq_wake_enabled ;
2015-12-21 15:26:31 +02:00
struct mutex reset_lock ;
2018-10-05 12:46:29 +08:00
unsigned long sleep_delay ;
2012-11-12 15:42:59 +01:00
} ;
2016-11-10 11:47:13 +08:00
static const struct i2c_hid_quirks {
__u16 idVendor ;
__u16 idProduct ;
__u32 quirks ;
} i2c_hid_quirks [ ] = {
2019-08-30 15:58:30 +08:00
{ USB_VENDOR_ID_WEIDA , HID_ANY_ID ,
2016-11-10 11:47:13 +08:00
I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV } ,
2017-11-07 13:28:00 +01:00
{ I2C_VENDOR_ID_HANTICK , I2C_PRODUCT_ID_HANTICK_5288 ,
2019-10-16 23:12:24 +08:00
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET } ,
2019-01-07 15:24:29 +08:00
{ USB_VENDOR_ID_ELAN , HID_ANY_ID ,
I2C_HID_QUIRK_BOGUS_IRQ } ,
2016-11-10 11:47:13 +08:00
{ 0 , 0 }
} ;
/*
* i2c_hid_lookup_quirk : return any quirks associated with a I2C HID device
* @ idVendor : the 16 - bit vendor ID
* @ idProduct : the 16 - bit product ID
*
* Returns : a u32 quirks value .
*/
static u32 i2c_hid_lookup_quirk ( const u16 idVendor , const u16 idProduct )
{
u32 quirks = 0 ;
int n ;
for ( n = 0 ; i2c_hid_quirks [ n ] . idVendor ; n + + )
if ( i2c_hid_quirks [ n ] . idVendor = = idVendor & &
( i2c_hid_quirks [ n ] . idProduct = = ( __u16 ) HID_ANY_ID | |
i2c_hid_quirks [ n ] . idProduct = = idProduct ) )
quirks = i2c_hid_quirks [ n ] . quirks ;
return quirks ;
}
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 ;
2017-11-07 13:28:00 +01:00
if ( wait & & ( ihid - > quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET ) ) {
msleep ( 100 ) ;
} else if ( wait ) {
2012-11-12 15:42:59 +01:00
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 ;
}
2014-02-10 12:58:49 -05:00
/**
* i2c_hid_set_or_send_report : forward an incoming report to the device
* @ client : the i2c_client of the device
* @ reportType : 0x03 for HID_FEATURE_REPORT ; 0x02 for HID_OUTPUT_REPORT
* @ reportID : the report ID
* @ buf : the actual data to transfer , without the report ID
* @ len : size of buf
* @ use_data : true : use SET_REPORT HID command , false : send plain OUTPUT report
*/
static int i2c_hid_set_or_send_report ( struct i2c_client * client , u8 reportType ,
u8 reportID , unsigned char * buf , size_t data_len , bool use_data )
2012-11-12 15:42:59 +01:00
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
u8 * args = ihid - > argsbuf ;
2014-02-10 12:58:49 -05:00
const struct i2c_hid_cmd * hidcmd ;
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 ) ;
2016-03-14 15:21:04 -07:00
u16 size ;
int args_len ;
int index = 0 ;
i2c_hid_dbg ( ihid , " %s \n " , __func__ ) ;
if ( data_len > ihid - > bufsize )
return - EINVAL ;
2012-11-12 15:42:59 +01:00
2016-03-14 15:21:04 -07:00
size = 2 /* size */ +
2012-11-12 15:42:59 +01:00
( reportID ? 1 : 0 ) /* reportID */ +
data_len /* buf */ ;
2016-03-14 15:21:04 -07:00
args_len = ( reportID > = 0x0F ? 1 : 0 ) /* optional third byte */ +
2012-11-12 15:42:59 +01:00
2 /* dataRegister */ +
size /* args */ ;
2014-02-10 12:58:49 -05:00
if ( ! use_data & & maxOutputLength = = 0 )
return - ENOSYS ;
2012-11-12 15:42:59 +01:00
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
*/
2014-02-10 12:58:49 -05:00
if ( use_data ) {
2013-06-17 16:15:06 -07:00
args [ index + + ] = dataRegister & 0xFF ;
args [ index + + ] = dataRegister > > 8 ;
2014-02-10 12:58:49 -05:00
hidcmd = & hid_set_report_cmd ;
2013-06-17 16:15:06 -07:00
} 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__ ) ;
2016-11-10 11:47:13 +08:00
/*
* Some devices require to send a command to wakeup before power on .
* The call will get a return value ( EREMOTEIO ) but device will be
* triggered and activated . After that , it goes like a normal device .
*/
if ( power_state = = I2C_HID_PWR_ON & &
ihid - > quirks & I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV ) {
ret = i2c_hid_command ( client , & hid_set_power_cmd , NULL , 0 ) ;
/* Device was already activated */
if ( ! ret )
goto set_pwr_exit ;
}
2012-11-12 15:42:59 +01:00
ret = __i2c_hid_command ( client , & hid_set_power_cmd , power_state ,
0 , NULL , 0 , NULL , 0 ) ;
2016-11-10 11:47:13 +08:00
2012-11-12 15:42:59 +01:00
if ( ret )
dev_err ( & client - > dev , " failed to change power setting. \n " ) ;
2016-11-10 11:47:13 +08:00
set_pwr_exit :
2012-11-12 15:42:59 +01:00
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__ ) ;
2015-12-21 15:26:31 +02:00
/*
* This prevents sending feature reports while the device is
* being reset . Otherwise we may lose the reset complete
* interrupt .
*/
mutex_lock ( & ihid - > reset_lock ) ;
2012-11-12 15:42:59 +01:00
ret = i2c_hid_set_power ( client , I2C_HID_PWR_ON ) ;
if ( ret )
2015-12-21 15:26:31 +02:00
goto out_unlock ;
2012-11-12 15:42:59 +01:00
2017-01-07 08:01:38 +11:00
/*
* The HID over I2C specification states that if a DEVICE needs time
* after the PWR_ON request , it should utilise CLOCK stretching .
* However , it has been observered that the Windows driver provides a
* 1 ms sleep between the PWR_ON and RESET requests and that some devices
* rely on this .
*/
usleep_range ( 1000 , 5000 ) ;
2012-11-12 15:42:59 +01:00
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 ) ;
}
2015-12-21 15:26:31 +02:00
out_unlock :
mutex_unlock ( & ihid - > reset_lock ) ;
return ret ;
2012-11-12 15:42:59 +01:00
}
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
{
2018-01-08 10:41:40 +08:00
int ret ;
u32 ret_size ;
2015-02-20 11:45:11 -06:00
int size = le16_to_cpu ( ihid - > hdesc . wMaxInputLength ) ;
if ( size > ihid - > bufsize )
size = ihid - > bufsize ;
2012-11-12 15:42:59 +01:00
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
}
2019-01-07 15:24:29 +08:00
if ( ihid - > quirks & I2C_HID_QUIRK_BOGUS_IRQ & & ret_size = = 0xffff ) {
dev_warn_once ( & ihid - > client - > dev , " %s: IRQ triggered but "
" there's no data \n " , __func__ ) ;
return ;
}
2018-06-22 12:25:49 -04:00
if ( ( ret_size > size ) | | ( ret_size < 2 ) ) {
2012-11-12 15:42:59 +01:00
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 ;
}
/*
* 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 ) ;
2014-11-20 00:46:37 +08:00
kfree ( ihid - > rawbuf ) ;
2012-12-05 15:02:54 +01:00
kfree ( ihid - > argsbuf ) ;
kfree ( ihid - > cmdbuf ) ;
ihid - > inbuf = NULL ;
2014-11-20 00:46:37 +08:00
ihid - > rawbuf = NULL ;
2012-12-05 15:02:54 +01:00
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 */
2017-09-08 10:55:27 -07:00
int args_len = sizeof ( __u8 ) + /* ReportID */
sizeof ( __u8 ) + /* optional ReportID byte */
2012-11-12 15:42:59 +01:00
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 ) ;
2014-11-20 00:46:37 +08:00
ihid - > rawbuf = 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 ) ;
2014-11-20 00:46:37 +08:00
if ( ! ihid - > inbuf | | ! ihid - > rawbuf | | ! ihid - > argsbuf | | ! ihid - > cmdbuf ) {
2012-12-05 15:02:54 +01:00
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 ,
2014-11-20 00:46:37 +08:00
report_number , ihid - > rawbuf , ask_count ) ;
2012-11-12 15:42:59 +01:00
if ( ret < 0 )
return ret ;
2014-11-20 00:46:37 +08:00
ret_count = ihid - > rawbuf [ 0 ] | ( ihid - > rawbuf [ 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 ) ;
2014-11-20 00:46:37 +08:00
memcpy ( buf , ihid - > rawbuf + 2 , count ) ;
2012-11-12 15:42:59 +01:00
return count ;
}
static int i2c_hid_output_raw_report ( struct hid_device * hid , __u8 * buf ,
2014-02-10 12:58:49 -05:00
size_t count , unsigned char report_type , bool use_data )
2012-11-12 15:42:59 +01:00
{
struct i2c_client * client = hid - > driver_data ;
2015-12-21 15:26:31 +02:00
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
2012-11-12 15:42:59 +01:00
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 ;
2015-12-21 15:26:31 +02:00
mutex_lock ( & ihid - > reset_lock ) ;
2013-01-31 17:50:02 +01:00
if ( report_id ) {
buf + + ;
count - - ;
}
2014-02-10 12:58:49 -05:00
ret = i2c_hid_set_or_send_report ( client ,
2012-11-12 15:42:59 +01:00
report_type = = HID_FEATURE_REPORT ? 0x03 : 0x02 ,
2014-02-10 12:58:49 -05:00
report_id , buf , count , use_data ) ;
2013-01-31 17:50:02 +01:00
if ( report_id & & ret > = 0 )
ret + + ; /* add report_id to the number of transfered bytes */
2015-12-21 15:26:31 +02:00
mutex_unlock ( & ihid - > reset_lock ) ;
2013-01-31 17:50:02 +01:00
return ret ;
2012-11-12 15:42:59 +01:00
}
2014-02-10 12:58:49 -05:00
static int i2c_hid_output_report ( struct hid_device * hid , __u8 * buf ,
size_t count )
2013-02-25 11:31:50 +01:00
{
2014-02-10 12:58:49 -05:00
return i2c_hid_output_raw_report ( hid , buf , count , HID_OUTPUT_REPORT ,
false ) ;
}
2013-02-25 11:31:50 +01:00
2014-02-10 12:58:49 -05:00
static int i2c_hid_raw_request ( struct hid_device * hid , unsigned char reportnum ,
__u8 * buf , size_t len , unsigned char rtype ,
int reqtype )
{
2013-02-25 11:31:50 +01:00
switch ( reqtype ) {
case HID_REQ_GET_REPORT :
2014-02-10 12:58:49 -05:00
return i2c_hid_get_raw_report ( hid , reportnum , buf , len , rtype ) ;
2013-02-25 11:31:50 +01:00
case HID_REQ_SET_REPORT :
2014-02-10 12:58:49 -05:00
if ( buf [ 0 ] ! = reportnum )
return - EINVAL ;
return i2c_hid_output_raw_report ( hid , buf , len , rtype , true ) ;
default :
return - EIO ;
2013-02-25 11:31:50 +01:00
}
}
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 ;
2018-09-19 11:46:23 +02:00
char * use_override ;
2012-11-12 15:42:59 +01:00
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 ;
2018-09-19 11:46:23 +02:00
use_override = i2c_hid_get_dmi_hid_report_desc_override ( client - > name ,
& rsize ) ;
2012-11-12 15:42:59 +01:00
2018-09-19 11:46:23 +02:00
if ( use_override ) {
rdesc = use_override ;
i2c_hid_dbg ( ihid , " Using a HID report descriptor override \n " ) ;
} else {
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 ;
}
2012-11-12 15:42:59 +01:00
}
i2c_hid_dbg ( ihid , " Report Descriptor: %*ph \n " , rsize , rdesc ) ;
ret = hid_parse_report ( hid , rdesc , rsize ) ;
2018-09-19 11:46:23 +02:00
if ( ! use_override )
kfree ( rdesc ) ;
2012-11-12 15:42:59 +01:00
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 ) {
2016-12-10 21:58:55 +01:00
disable_irq ( client - > irq ) ;
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 ) ;
2016-12-10 21:58:55 +01:00
enable_irq ( client - > irq ) ;
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 ;
}
return 0 ;
}
static void i2c_hid_stop ( struct hid_device * hid )
{
hid - > claimed = 0 ;
}
static int i2c_hid_open ( struct hid_device * hid )
{
struct i2c_client * client = hid - > driver_data ;
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
2017-06-06 23:59:35 -07:00
set_bit ( I2C_HID_STARTED , & ihid - > flags ) ;
return 0 ;
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 ) ;
2017-06-06 23:59:35 -07:00
clear_bit ( I2C_HID_STARTED , & ihid - > flags ) ;
2012-11-12 15:42:59 +01:00
}
2017-07-24 09:46:18 -07:00
struct hid_ll_driver i2c_hid_ll_driver = {
2012-11-12 15:42:59 +01:00
. parse = i2c_hid_parse ,
. start = i2c_hid_start ,
. stop = i2c_hid_stop ,
. open = i2c_hid_open ,
. close = i2c_hid_close ,
2014-02-10 12:58:49 -05:00
. output_report = i2c_hid_output_report ,
. raw_request = i2c_hid_raw_request ,
2012-11-12 15:42:59 +01:00
} ;
2017-07-24 09:46:18 -07:00
EXPORT_SYMBOL_GPL ( i2c_hid_ll_driver ) ;
2012-11-12 15:42:59 +01:00
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 ) ;
2016-11-21 15:21:27 +01:00
unsigned long irqflags = 0 ;
2012-11-12 15:42:59 +01:00
int ret ;
2016-10-13 11:30:44 +02:00
dev_dbg ( & client - > dev , " Requesting IRQ: %d \n " , client - > irq ) ;
2012-11-12 15:42:59 +01:00
2016-11-21 15:21:27 +01:00
if ( ! irq_get_trigger_type ( client - > irq ) )
irqflags = IRQF_TRIGGER_LOW ;
2016-10-13 11:30:44 +02:00
ret = request_threaded_irq ( client - > irq , NULL , i2c_hid_irq ,
2016-11-21 15:21:27 +01:00
irqflags | IRQF_ONESHOT , client - > name , ihid ) ;
2012-11-12 15:42:59 +01:00
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 " ,
2016-10-13 11:30:44 +02: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 ;
2014-05-08 09:26:19 -04:00
/* i2c hid fetch using a fixed descriptor size (30 bytes) */
2018-09-19 11:46:23 +02:00
if ( i2c_hid_get_dmi_i2c_hid_desc_override ( client - > name ) ) {
i2c_hid_dbg ( ihid , " Using a HID descriptor override \n " ) ;
ihid - > hdesc =
* i2c_hid_get_dmi_i2c_hid_desc_override ( client - > name ) ;
} else {
i2c_hid_dbg ( ihid , " Fetching the HID descriptor \n " ) ;
ret = i2c_hid_command ( client , & hid_descr_cmd ,
ihid - > hdesc_buffer ,
sizeof ( struct i2c_hid_desc ) ) ;
if ( ret ) {
dev_err ( & client - > dev , " hid_descr_cmd failed \n " ) ;
return - ENODEV ;
}
2012-11-12 15:42:59 +01:00
}
2014-05-08 09:26:19 -04:00
/* Validate the length of HID descriptor, the 4 first bytes:
* bytes 0 - 1 - > length
* bytes 2 - 3 - > bcdVersion ( has to be 1.00 ) */
2012-11-12 15:42:59 +01:00
/* 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 ;
}
2014-05-08 09:26:19 -04:00
/* Descriptor length should be 30 bytes as per the specification */
dsize = le16_to_cpu ( hdesc - > wHIDDescLength ) ;
if ( dsize ! = sizeof ( struct i2c_hid_desc ) ) {
dev_err ( & client - > dev , " weird size of HID descriptor (%u) \n " ,
dsize ) ;
2012-11-12 15:42:59 +01:00
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
2018-04-03 15:16:34 +02:00
static const struct acpi_device_id i2c_hid_acpi_blacklist [ ] = {
/*
* The CHPN0001 ACPI device , which is used to describe the Chipone
* ICN8505 controller , has a _CID of PNP0C50 but is not HID compatible .
*/
{ " CHPN0001 " , 0 } ,
{ } ,
} ;
2013-01-09 16:43:08 +02:00
static int i2c_hid_acpi_pdata ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
2017-06-05 19:40:46 +03:00
static guid_t i2c_hid_guid =
GUID_INIT ( 0x3CDFF6F7 , 0x4267 , 0x4555 ,
0xAD , 0x05 , 0xB3 , 0x0A , 0x3D , 0x89 , 0x38 , 0xDE ) ;
2013-12-19 20:38:19 +08:00
union acpi_object * obj ;
2013-01-09 16:43:08 +02:00
struct acpi_device * adev ;
acpi_handle handle ;
handle = ACPI_HANDLE ( & client - > dev ) ;
2018-04-03 15:16:33 +02:00
if ( ! handle | | acpi_bus_get_device ( handle , & adev ) ) {
dev_err ( & client - > dev , " Error could not get ACPI device \n " ) ;
2013-01-09 16:43:08 +02:00
return - ENODEV ;
2018-04-03 15:16:33 +02:00
}
2013-01-09 16:43:08 +02:00
2018-04-03 15:16:34 +02:00
if ( acpi_match_device_ids ( adev , i2c_hid_acpi_blacklist ) = = 0 )
2013-01-09 16:43:08 +02:00
return - ENODEV ;
2017-06-05 19:40:46 +03:00
obj = acpi_evaluate_dsm_typed ( handle , & i2c_hid_guid , 1 , 1 , NULL ,
2013-12-19 20:38:19 +08:00
ACPI_TYPE_INTEGER ) ;
if ( ! obj ) {
2018-04-03 15:16:33 +02:00
dev_err ( & client - > dev , " Error _DSM call to get HID descriptor address failed \n " ) ;
2013-01-09 16:43:08 +02:00
return - ENODEV ;
}
2013-12-19 20:38:19 +08:00
pdata - > hid_descriptor_address = obj - > integer . value ;
ACPI_FREE ( obj ) ;
2013-01-09 16:43:08 +02:00
2016-10-13 11:30:44 +02:00
return 0 ;
2013-01-09 16:43:08 +02:00
}
2017-05-09 10:04:36 +02:00
static void i2c_hid_acpi_fix_up_power ( struct device * dev )
{
struct acpi_device * adev ;
2018-01-19 16:35:04 +02:00
adev = ACPI_COMPANION ( dev ) ;
if ( adev )
2017-05-09 10:04:36 +02:00
acpi_device_fix_up_power ( adev ) ;
}
2013-01-09 16:43:08 +02:00
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 ;
}
2017-05-09 10:04:36 +02:00
static inline void i2c_hid_acpi_fix_up_power ( struct device * dev ) { }
2013-01-09 16:43:08 +02:00
# endif
2013-06-13 09:50:35 +02:00
# ifdef CONFIG_OF
static int i2c_hid_of_probe ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
struct device * dev = & client - > dev ;
u32 val ;
int ret ;
ret = of_property_read_u32 ( dev - > of_node , " hid-descr-addr " , & val ) ;
if ( ret ) {
dev_err ( & client - > dev , " HID register address not provided \n " ) ;
return - ENODEV ;
}
if ( val > > 16 ) {
dev_err ( & client - > dev , " Bad HID register address: 0x%08x \n " ,
val ) ;
return - EINVAL ;
}
pdata - > hid_descriptor_address = val ;
return 0 ;
}
static const struct of_device_id i2c_hid_of_match [ ] = {
{ . compatible = " hid-over-i2c " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , i2c_hid_of_match ) ;
# else
static inline int i2c_hid_of_probe ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
return - ENODEV ;
}
# endif
2017-10-03 11:19:21 -07:00
static void i2c_hid_fwnode_probe ( struct i2c_client * client ,
struct i2c_hid_platform_data * pdata )
{
u32 val ;
if ( ! device_property_read_u32 ( & client - > dev , " post-power-on-delay-ms " ,
& val ) )
pdata - > post_power_delay_ms = val ;
}
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 ) ;
2016-10-13 11:30:44 +02:00
if ( ! client - > irq ) {
dev_err ( & client - > dev ,
" HID over i2c has not been provided an Int IRQ \n " ) ;
return - EINVAL ;
}
2016-10-13 11:30:45 +02:00
if ( client - > irq < 0 ) {
if ( client - > irq ! = - EPROBE_DEFER )
dev_err ( & client - > dev ,
" HID over i2c doesn't have a valid IRQ \n " ) ;
return client - > irq ;
}
2018-06-21 19:27:16 -07:00
ihid = devm_kzalloc ( & client - > dev , sizeof ( * ihid ) , GFP_KERNEL ) ;
2012-11-12 15:42:59 +01:00
if ( ! ihid )
return - ENOMEM ;
2013-06-13 09:50:35 +02:00
if ( client - > dev . of_node ) {
ret = i2c_hid_of_probe ( client , & ihid - > pdata ) ;
if ( ret )
2018-06-21 19:27:16 -07:00
return ret ;
2013-06-13 09:50:35 +02:00
} else if ( ! platform_data ) {
2013-01-09 16:43:08 +02:00
ret = i2c_hid_acpi_pdata ( client , & ihid - > pdata ) ;
2018-04-03 15:16:33 +02:00
if ( ret )
2018-06-21 19:27:16 -07:00
return ret ;
2013-01-09 16:43:08 +02:00
} else {
ihid - > pdata = * platform_data ;
}
2017-10-03 11:19:21 -07:00
/* Parse platform agnostic common properties from ACPI / device tree */
i2c_hid_fwnode_probe ( client , & ihid - > pdata ) ;
2018-06-21 19:27:17 -07:00
ihid - > pdata . supplies [ 0 ] . supply = " vdd " ;
ihid - > pdata . supplies [ 1 ] . supply = " vddl " ;
ret = devm_regulator_bulk_get ( & client - > dev ,
ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
if ( ret )
return ret ;
ret = regulator_bulk_enable ( ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
if ( ret < 0 )
return ret ;
2017-02-09 18:03:57 -08:00
if ( ihid - > pdata . post_power_delay_ms )
msleep ( ihid - > pdata . post_power_delay_ms ) ;
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 ) ;
2015-12-21 15:26:31 +02:00
mutex_init ( & ihid - > reset_lock ) ;
2012-11-12 15:42:59 +01:00
/* 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 )
2017-02-09 18:03:57 -08:00
goto err_regulator ;
2012-11-12 15:42:59 +01:00
2017-05-09 10:04:36 +02:00
i2c_hid_acpi_fix_up_power ( & client - > dev ) ;
2016-05-19 10:46:24 +08:00
device_enable_async_suspend ( & client - > dev ) ;
2014-01-29 11:24:36 +02:00
2018-05-09 12:12:15 -07:00
/* Make sure there is something at this address */
ret = i2c_smbus_read_byte ( client ) ;
if ( ret < 0 ) {
dev_dbg ( & client - > dev , " nothing at this address: %d \n " , ret ) ;
ret = - ENXIO ;
2019-10-16 23:12:24 +08:00
goto err_regulator ;
2018-05-09 12:12:15 -07:00
}
2012-11-12 15:42:59 +01:00
ret = i2c_hid_fetch_hid_descriptor ( ihid ) ;
if ( ret < 0 )
2019-10-16 23:12:24 +08:00
goto err_regulator ;
2012-11-12 15:42:59 +01:00
ret = i2c_hid_init_irq ( client ) ;
if ( ret < 0 )
2019-10-16 23:12:24 +08:00
goto err_regulator ;
2012-11-12 15:42:59 +01:00
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 - > dev . parent = & client - > dev ;
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 ) ;
2015-09-28 15:15:08 +03:00
strlcpy ( hid - > phys , dev_name ( & client - > dev ) , sizeof ( hid - > phys ) ) ;
2012-11-12 15:42:59 +01:00
2016-11-10 11:47:13 +08:00
ihid - > quirks = i2c_hid_lookup_quirk ( hid - > vendor , hid - > product ) ;
2012-11-12 15:42:59 +01:00
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 :
2016-10-13 11:30:44 +02:00
free_irq ( client - > irq , ihid ) ;
2012-11-12 15:42:59 +01:00
2017-02-09 18:03:57 -08:00
err_regulator :
2018-06-21 19:27:17 -07:00
regulator_bulk_disable ( ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
2012-11-20 17:09:40 +01:00
i2c_hid_free_buffers ( ihid ) ;
2012-11-12 15:42:59 +01:00
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 ) ;
2016-10-13 11:30:44 +02:00
free_irq ( client - > irq , ihid ) ;
2012-11-12 15:42:59 +01:00
2012-12-04 16:27:54 +01:00
if ( ihid - > bufsize )
i2c_hid_free_buffers ( ihid ) ;
2018-06-21 19:27:17 -07:00
regulator_bulk_disable ( ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
2012-11-12 15:42:59 +01:00
return 0 ;
}
2016-06-21 18:27:45 +08:00
static void i2c_hid_shutdown ( struct i2c_client * client )
{
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
free_irq ( client - > irq , ihid ) ;
}
2012-11-12 15:42:59 +01:00
# ifdef CONFIG_PM_SLEEP
static int i2c_hid_suspend ( struct device * dev )
{
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-07-11 16:34:18 -07:00
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
struct hid_device * hid = ihid - > hid ;
2016-03-08 15:03:23 -08:00
int ret ;
2015-07-30 14:49:00 -07:00
int wake_status ;
2012-11-12 15:42:59 +01:00
2016-03-08 15:03:23 -08:00
if ( hid - > driver & & hid - > driver - > suspend ) {
2015-07-07 21:58:02 +02:00
ret = hid - > driver - > suspend ( hid , PMSG_SUSPEND ) ;
2016-03-08 15:03:23 -08:00
if ( ret < 0 )
return ret ;
}
2019-10-16 23:12:24 +08:00
/* Save some power */
i2c_hid_set_power ( client , I2C_HID_PWR_SLEEP ) ;
2016-03-08 15:03:23 -08:00
2019-10-16 23:12:24 +08:00
disable_irq ( client - > irq ) ;
2015-07-07 21:58:02 +02:00
2015-07-30 14:49:00 -07:00
if ( device_may_wakeup ( & client - > dev ) ) {
2016-10-13 11:30:44 +02:00
wake_status = enable_irq_wake ( client - > irq ) ;
2015-07-30 14:49:00 -07:00
if ( ! wake_status )
ihid - > irq_wake_enabled = true ;
else
hid_warn ( hid , " Failed to enable irq wake: %d \n " ,
wake_status ) ;
2017-02-09 18:03:57 -08:00
} else {
2018-06-21 19:27:17 -07:00
regulator_bulk_disable ( ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
2015-07-30 14:49:00 -07:00
}
2012-11-12 15:42:59 +01:00
2016-03-08 15:03:23 -08:00
return 0 ;
2012-11-12 15:42:59 +01:00
}
static int i2c_hid_resume ( struct device * dev )
{
int ret ;
struct i2c_client * client = to_i2c_client ( dev ) ;
2014-07-11 16:34:18 -07:00
struct i2c_hid * ihid = i2c_get_clientdata ( client ) ;
struct hid_device * hid = ihid - > hid ;
2015-07-30 14:49:00 -07:00
int wake_status ;
2012-11-12 15:42:59 +01:00
2017-02-09 18:03:57 -08:00
if ( ! device_may_wakeup ( & client - > dev ) ) {
2018-06-21 19:27:17 -07:00
ret = regulator_bulk_enable ( ARRAY_SIZE ( ihid - > pdata . supplies ) ,
ihid - > pdata . supplies ) ;
if ( ret )
hid_warn ( hid , " Failed to enable supplies: %d \n " , ret ) ;
2017-02-09 18:03:57 -08:00
if ( ihid - > pdata . post_power_delay_ms )
msleep ( ihid - > pdata . post_power_delay_ms ) ;
} else if ( ihid - > irq_wake_enabled ) {
2016-10-13 11:30:44 +02:00
wake_status = disable_irq_wake ( client - > irq ) ;
2015-07-30 14:49:00 -07:00
if ( ! wake_status )
ihid - > irq_wake_enabled = false ;
else
hid_warn ( hid , " Failed to disable irq wake: %d \n " ,
wake_status ) ;
}
2012-11-12 15:42:59 +01:00
2016-10-13 11:30:44 +02:00
enable_irq ( client - > irq ) ;
2018-09-06 10:55:18 +08:00
/* Instead of resetting device, simply powers the device on. This
* solves " incomplete reports " on Raydium devices 2386 : 3118 and
2018-09-19 20:52:45 +02:00
* 2386 : 4 B33 and fixes various SIS touchscreens no longer sending
* data after a suspend / resume .
2018-09-06 10:55:18 +08:00
*/
ret = i2c_hid_set_power ( client , I2C_HID_PWR_ON ) ;
2016-03-08 15:03:23 -08:00
if ( ret )
return ret ;
2014-07-11 16:34:18 -07:00
if ( hid - > driver & & hid - > driver - > reset_resume ) {
ret = hid - > driver - > reset_resume ( hid ) ;
return ret ;
}
2012-11-12 15:42:59 +01:00
return 0 ;
}
# endif
2014-01-29 11:24:36 +02:00
static const struct dev_pm_ops i2c_hid_pm = {
SET_SYSTEM_SLEEP_PM_OPS ( i2c_hid_suspend , i2c_hid_resume )
} ;
2012-11-12 15:42:59 +01:00
static const struct i2c_device_id i2c_hid_id_table [ ] = {
2012-12-04 16:27:42 +01:00
{ " hid " , 0 } ,
2016-03-08 11:25:39 -08:00
{ " hid-over-i2c " , 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 " ,
. pm = & i2c_hid_pm ,
2013-01-09 16:43:08 +02:00
. acpi_match_table = ACPI_PTR ( i2c_hid_acpi_match ) ,
2013-06-13 09:50:35 +02:00
. of_match_table = of_match_ptr ( i2c_hid_of_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 ,
2016-06-21 18:27:45 +08:00
. shutdown = i2c_hid_shutdown ,
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 " ) ;