分类:
2009-01-15 10:46:37
|
找到一篇半成的代码,研究研究, 看看能不能处理掉其中的问题
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "tsmb_eeprom.h"
/*----实现代码:tsmb_eeprom模块实现代码----*/
struct i2c_client *new_client;
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x50,
I2C_CLIENT_END };/*0x50 is device address*/
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(tsmb_eeprom);
static DECLARE_WAIT_QUEUE_HEAD(tsmb_eeprom_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(tsmb_eeprom_write_wait);
static DECLARE_MUTEX(tsmb_eeprom_read_sem);
static DECLARE_MUTEX(tsmb_eeprom_write_sem);
static int tsmb_eeprom_attach_adapter(struct i2c_adapter *adapter);
static int tsmb_eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
static int tsmb_eeprom_detach_client(struct i2c_client *client);
/* Each client has this additional data */
struct eeprom_data
{
struct i2c_client client;
u8 read; /* Remember last read value */
u8 write; /* Remember last write value */
};
/* This is the driver that will be inserted */
static struct i2c_driver tsmb_eeprom_driver = {
.driver =
{
.name = "tsmb_eeprom",
},
.id = 0xf005,
.attach_adapter = tsmb_eeprom_attach_adapter,
.detach_client = tsmb_eeprom_detach_client,
};
static int tsmb_eeprom_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, tsmb_eeprom_detect);
}
/* This function is called by i2c_probe */
static int tsmb_eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct eeprom_data *data;
int err = 0;
const char *client_name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
goto exit;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL)))
{
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
new_client->addr = address;
printk("address==%x\n",new_client->addr);
new_client->adapter = adapter;
new_client->driver = &tsmb_eeprom_driver;
new_client->flags = 0;
client_name = "tsmb_eeprom";
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
/*printk("client's name is %s in tvp5146_detect\n",new_client->name);*/
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
exit_free:
kfree(data);
exit:
return err;
}
static int tsmb_eeprom_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client));
return 0;
}
static int tsmb_eeprom_open(struct inode * inode, struct file * filp)
{
struct i2c_client *client;
struct i2c_dev *i2c_dev;
client = kmalloc(sizeof(*client), GFP_KERNEL);
if (!client)
{
return -ENOMEM;
}
client=new_client;
client->adapter = client->adapter;
filp->private_data = client;
return 0;
}
static int tsmb_eeprom_release(struct inode * inode, struct file * filp)
{
return 0;
}
static loff_t tsmb_eeprom_llseek (struct file *filp, loff_t off, int whence)
{
//struct i2c_dev *dev = filp->private_data;
loff_t newpos;
filp->private_data=new_client;
switch(whence)
{
case SEEK_SET:
newpos = off;
break;
case SEEK_CUR:
newpos = filp->f_pos + off;
break;
case SEEK_END:
//newpos = (filp->private_data)->size + off;
break;
default: /* can't happen */
return -EINVAL;
}
if (newpos < 0)
return -EINVAL;
filp->f_pos = newpos;
return newpos;
}
static ssize_t tsmb_eeprom_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
ssize_t ret;
int result,i;
struct i2c_client *client = new_client;
struct i2c_msg msg[1];
char *tmp;
u8 val;
printk("this is in reading!\n");
if(down_interruptible(&tsmb_eeprom_read_sem))
goto out;
tmp=kmalloc(count,GFP_KERNEL);
if (tmp == NULL)
return - ENOMEM;
memset(tmp,0,count);
result=i2c_master_recv(client, tmp ,count);
printk("read result===%x\n",result);
ret = copy_to_user(buffer, tmp, count);
if(ret != 0)
{
kfree(tmp);
return -EFAULT;
}
out:
{
up(&tsmb_eeprom_read_sem);
return 0;
}
kfree(tmp);
return ret;
}
static ssize_t tsmb_eeprom_write(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
ssize_t ret;
int result,i;
struct i2c_client *client=new_client;
struct i2c_msg msg[1];
char *tmp;
if(down_interruptible(&tsmb_eeprom_write_sem))
goto out;
printk("this is in writting!\n");
tmp=kmalloc(count,GFP_KERNEL);
if (tmp == NULL)
return - ENOMEM;
ret = copy_from_user(tmp, buffer, count);
if(ret != 0)
{
kfree(tmp);
return -EFAULT;
}
result=i2c_master_send(client,tmp ,count);
printk("write result===%x\n",result);
out:
{
up(&tsmb_eeprom_write_sem);
return 0;
}
kfree(tmp);
return result;
}
/*to user*/
static struct file_operations tsmb_eeprom_fops = {
.owner = THIS_MODULE,
.open=tsmb_eeprom_open,
//.poll = tsmb_eeprom_select,
.read = tsmb_eeprom_read,
.write = tsmb_eeprom_write,
.llseek = tsmb_eeprom_llseek,
.release=tsmb_eeprom_release,
};
static int __init tsmb_eeprom_init(void)
{
int ret,result;
result = register_chrdev(TSMB_EEPROM_MAJOR, DEVICE_NAME, &tsmb_eeprom_fops);
if (result < 0)
{
printk(KERN_ERR DEVICE_NAME ": Unable to get major %d\n", TSMB_EEPROM_MAJOR);
return(result);
}
ret=i2c_add_driver(&tsmb_eeprom_driver);
if (ret)
goto out_unreg_class;
printk(KERN_ERR DEVICE_NAME ": init OK\n");
return 0;
out_unreg_class:
unregister_chrdev(TSMB_EEPROM_MAJOR, DEVICE_NAME);
}
static void __exit tsmb_eeprom_exit(void)
{
i2c_del_driver(&tsmb_eeprom_driver);
unregister_chrdev(TSMB_EEPROM_MAJOR, DEVICE_NAME);
}
module_init(tsmb_eeprom_init);
module_exit(tsmb_eeprom_exit);
MODULE_DESCRIPTION("I2C EEPROM driver");
MODULE_LICENSE("GPL");