Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1146278
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2016-11-25 16:12:30

 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;
}










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