Chinaunix首页 | 论坛 | 博客
  • 博客访问: 318264
  • 博文数量: 68
  • 博客积分: 1501
  • 博客等级: 上尉
  • 技术积分: 1010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-30 09:52
文章分类

全部博文(68)

文章存档

2010年(1)

2009年(67)

我的朋友

分类:

2009-01-15 10:46:37

文件: i2c源代码情景分析].pdf
大小: 508KB
下载: 下载

找到一篇半成的代码,研究研究, 看看能不能处理掉其中的问题

#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");

阅读(1224) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~