2005-04-16 15:20:36 -07:00
/*
i2c - stub . c - Part of lm_sensors , Linux kernel modules for hardware
monitoring
Copyright ( c ) 2004 Mark M . Hoffman < mhoffman @ lightlink . 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 ; either version 2 of the License , or
( at your option ) any later version .
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 .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# define DEBUG 1
# include <linux/init.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/i2c.h>
2006-08-13 23:46:44 +02:00
static unsigned short chip_addr ;
module_param ( chip_addr , ushort , S_IRUGO ) ;
MODULE_PARM_DESC ( chip_addr , " Chip address (between 0x03 and 0x77) \n " ) ;
2005-04-16 15:20:36 -07:00
static u8 stub_pointer ;
static u8 stub_bytes [ 256 ] ;
static u16 stub_words [ 256 ] ;
/* Return -1 on error. */
static s32 stub_xfer ( struct i2c_adapter * adap , u16 addr , unsigned short flags ,
char read_write , u8 command , int size , union i2c_smbus_data * data )
{
s32 ret ;
2006-08-13 23:46:44 +02:00
if ( addr ! = chip_addr )
return - ENODEV ;
2005-04-16 15:20:36 -07:00
switch ( size ) {
case I2C_SMBUS_QUICK :
dev_dbg ( & adap - > dev , " smbus quick - addr 0x%02x \n " , addr ) ;
ret = 0 ;
break ;
case I2C_SMBUS_BYTE :
if ( read_write = = I2C_SMBUS_WRITE ) {
stub_pointer = command ;
dev_dbg ( & adap - > dev , " smbus byte - addr 0x%02x, "
" wrote 0x%02x. \n " ,
addr , command ) ;
} else {
data - > byte = stub_bytes [ stub_pointer + + ] ;
dev_dbg ( & adap - > dev , " smbus byte - addr 0x%02x, "
" read 0x%02x. \n " ,
addr , data - > byte ) ;
}
ret = 0 ;
break ;
case I2C_SMBUS_BYTE_DATA :
if ( read_write = = I2C_SMBUS_WRITE ) {
stub_bytes [ command ] = data - > byte ;
dev_dbg ( & adap - > dev , " smbus byte data - addr 0x%02x, "
" wrote 0x%02x at 0x%02x. \n " ,
addr , data - > byte , command ) ;
} else {
data - > byte = stub_bytes [ command ] ;
dev_dbg ( & adap - > dev , " smbus byte data - addr 0x%02x, "
" read 0x%02x at 0x%02x. \n " ,
addr , data - > byte , command ) ;
}
stub_pointer = command + 1 ;
ret = 0 ;
break ;
case I2C_SMBUS_WORD_DATA :
if ( read_write = = I2C_SMBUS_WRITE ) {
stub_words [ command ] = data - > word ;
dev_dbg ( & adap - > dev , " smbus word data - addr 0x%02x, "
" wrote 0x%04x at 0x%02x. \n " ,
addr , data - > word , command ) ;
} else {
data - > word = stub_words [ command ] ;
dev_dbg ( & adap - > dev , " smbus word data - addr 0x%02x, "
" read 0x%04x at 0x%02x. \n " ,
addr , data - > word , command ) ;
}
ret = 0 ;
break ;
default :
dev_dbg ( & adap - > dev , " Unsupported I2C/SMBus command \n " ) ;
ret = - 1 ;
break ;
} /* switch (size) */
return ret ;
}
static u32 stub_func ( struct i2c_adapter * adapter )
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA ;
}
2006-09-03 22:39:46 +02:00
static const struct i2c_algorithm smbus_algorithm = {
2005-04-16 15:20:36 -07:00
. functionality = stub_func ,
. smbus_xfer = stub_xfer ,
} ;
static struct i2c_adapter stub_adapter = {
. owner = THIS_MODULE ,
. class = I2C_CLASS_HWMON ,
. algo = & smbus_algorithm ,
. name = " SMBus stub driver " ,
} ;
static int __init i2c_stub_init ( void )
{
2006-08-13 23:46:44 +02:00
if ( ! chip_addr ) {
printk ( KERN_ERR " i2c-stub: Please specify a chip address \n " ) ;
return - ENODEV ;
}
if ( chip_addr < 0x03 | | chip_addr > 0x77 ) {
printk ( KERN_ERR " i2c-stub: Invalid chip address 0x%02x \n " ,
chip_addr ) ;
return - EINVAL ;
}
printk ( KERN_INFO " i2c-stub: Virtual chip at 0x%02x \n " , chip_addr ) ;
2005-04-16 15:20:36 -07:00
return i2c_add_adapter ( & stub_adapter ) ;
}
static void __exit i2c_stub_exit ( void )
{
i2c_del_adapter ( & stub_adapter ) ;
}
MODULE_AUTHOR ( " Mark M. Hoffman <mhoffman@lightlink.com> " ) ;
MODULE_DESCRIPTION ( " I2C stub driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
module_init ( i2c_stub_init ) ;
module_exit ( i2c_stub_exit ) ;