linux2.6.28 i2c-bus driver

i2c-dev.c - i2c-bus driver, char device interface

i2c-core.c这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。
  i2c-dev.c实 现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过适配器访设备时的主设备号都为89,次设备号为0-255。I2c- dev.c并没有针对特定的设备而设计,只是提供了通用的read(),write(),和ioctl()等接口,应用层可以借用这些接口访问挂接在适配 器上的I2C设备的存储空间或寄存器,并控制I2C设备的工作方式。
  busses文件夹这个文件中包含了一些I2C总线的驱动,如针对S3C2410,S3C2440,S3C6410等处理器的I2C控制器驱动为i2c-s3c2410.c.
  algos文件夹实现了一些I2C总线适配器的algorithm.

图片
/

//

/*

  • An i2c_dev represents an i2c_adapter … an I2C or SMBus master, not a
  • slave (i2c_client) with which messages will be exchanged. It’s coupled
  • with a character special file which is accessed by user mode drivers.
  • The list of i2c_dev structures is parallel to the i2c_adapter lists
  • maintained by the driver model, and is updated using notifications
  • delivered to the i2cdev_driver.
    */
    struct i2c_dev {
    struct list_head list;
    struct i2c_adapter *adap;
    struct device *dev;
    };
    //

module_init(i2c_dev_init);
static int __init i2c_dev_init(void)
{
int res;
printk(KERN_INFO “i2c /dev entries driver\n”);
res = register_chrdev(I2C_MAJOR, “i2c”, &i2cdev_fops);
//通过class_create()函数初始化一个类i2c_dev,这个类稍后需要使用,用于在/dev/i2c-0下自动创建设备
i2c_dev_class = class_create(THIS_MODULE, “i2c-dev”);
res = i2c_add_driver(&i2cdev_driver);
}
//

static struct i2c_driver i2cdev_driver = {
.driver = {
.name = “dev_driver”,
},
//通过i2c driver中的attach_adapter方法来实现将adapter和对应的驱动绑定
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
};
//

static int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
int res;

i2c_dev = get_free_i2c_dev(adap);
/* register this i2c device with the driver core */
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
                 MKDEV(I2C_MAJOR, adap->nr), NULL,
                 "i2c-%d", adap->nr);
res = device_create_file(i2c_dev->dev, &dev_attr_name);
return res;

}
//

// res = register_chrdev(I2C_MAJOR, “i2c”, &i2cdev_fops);
//此处是/dev/i2c这个设备文件的操作结构(字符)
//还有一种操作这个设备的方法是 文件中的at24_bin_read at24_bin_write
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
//

static int i2cdev_open(struct inode *inode, struct file *file)
{
unsigned int minor = iminor(inode);
struct i2c_client *client;
struct i2c_adapter *adap;
struct i2c_dev *i2c_dev;
int ret = 0;

lock_kernel();

//获得 struct i2c_dev
i2c_dev = i2c_dev_get_by_minor(minor);

//获得 i2c_adapter
adap = i2c_get_adapter(i2c_dev->adap->nr);

/* This creates an anonymous i2c_client, which may later be
 * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
 *
 * This client is ** NEVER REGISTERED ** with the driver model
 * or I2C core code!!  It just holds private copies of addressing
 * information and maybe a PEC flag.
 */
client = kzalloc(sizeof(*client), GFP_KERNEL);

snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);

执行完i2c_add_numbered_adapter函数后,内核的i2c总线上已有adapter device和client device
//< >i2c_add_driver(&at24_driver) 注册的是adapter的驱动adapter driver
//at24_driver相当于adapter driver?
// client->driver = &i2cdev_driver;
// i2cdev_driver相当于client driver??
client->driver = &i2cdev_driver;

client->adapter = adap;
file->private_data = client;

out:
unlock_kernel();
return ret;
}
//

static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t count,
loff_t *offset)
{
int ret;
char *tmp;
//见 i2cdev_open里给struct i2c_client *client 赋值
struct i2c_client *client = (struct i2c_client *)file->private_data;

if (count > 8192)
    count = 8192;

tmp = kmalloc(count,GFP_KERNEL);
if (tmp==NULL)
    return -ENOMEM;
if (copy_from_user(tmp,buf,count)) {
    kfree(tmp);
    return -EFAULT;
}

pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",
    iminor(file->f_path.dentry->d_inode), count);

//发送
ret = i2c_master_send(client,tmp,count);
kfree(tmp);
return ret;
}

//

/**

  • i2c_master_send - issue a single I2C message in master transmit mode

  • @client: Handle to slave device

  • @buf: Data that will be written to the slave

  • @count: How many bytes to write

  • Returns negative errno, or else the number of bytes written.
    */
    int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
    {
    int ret;
    struct i2c_adapter *adap=client->adapter;
    struct i2c_msg msg;

    msg.addr = client->addr;
    msg.flags = client->flags & I2C_M_TEN;
    msg.len = count;
    msg.buf = (char *)buf;

    ret = i2c_transfer(adap, &msg, 1);

    /* If everything went ok (i.e. 1 msg transmitted), return #bytes
    transmitted, else error code. */
    return (ret == 1) ? count : ret;
    }

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值