iic二

、driver/i2c/i2c-core.c

static int __init i2c_init(void)
{
        int retval;

        retval = bus_register(&i2c_bus_type);
        if (retval)
                return retval;
        retval = class_register(&i2c_adapter_class);
        if (retval)
                goto bus_err;
        retval = i2c_add_driver(&dummy_driver);
        if (retval)
                goto class_err;
        return 0;

class_err:
        class_unregister(&i2c_adapter_class);
bus_err:
        bus_unregister(&i2c_bus_type);
        return retval;
}

struct bus_type i2c_bus_type = {
        .name           = "i2c",
        .dev_attrs      = i2c_dev_attrs,
        .match          = i2c_device_match,
        .uevent         = i2c_device_uevent,
        .probe          = i2c_device_probe,
        .remove         = i2c_device_remove,
        .shutdown       = i2c_device_shutdown,
        .suspend        = i2c_device_suspend,
        .resume         = i2c_device_resume,
};

static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
        struct i2c_client       *client = to_i2c_client(dev);
        struct i2c_driver       *driver = to_i2c_driver(drv);

        /* match on an id table if there is one */
        if (driver->id_table)
                return i2c_match_id(driver->id_table, client) != NULL;

        return 0;
}

 

static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
                                                const struct i2c_client *client)
{
        while (id->name[0]) {
                if (strcmp(client->name, id->name) == 0)
                        return id;
                id++;
        }
        return NULL;
}

static int i2c_device_probe(struct device *dev)
{
        struct i2c_client       *client = to_i2c_client(dev);
        struct i2c_driver       *driver = to_i2c_driver(dev->driver);
        int status;

        if (!driver->probe || !driver->id_table)
                return -ENODEV;
        client->driver = driver;
        if (!device_can_wakeup(&client->dev))
                device_init_wakeup(&client->dev,
                                        client->flags & I2C_CLIENT_WAKE);
        dev_dbg(dev, "probe\n");

        status = driver->probe(client, i2c_match_id(driver->id_table, client));
        if (status)
                client->driver = NULL;
        return status;
}

postcore_initcall(i2c_init);

二、driver/i2c/i2c-dev.c

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);
        if (res)
                goto out;

        i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
        if (IS_ERR(i2c_dev_class)) {
                res = PTR_ERR(i2c_dev_class);
                goto out_unreg_chrdev;
        }

        res = i2c_add_driver(&i2cdev_driver);
        if (res)
                goto out_unreg_class;
        return 0;

out_unreg_class:
        class_destroy(i2c_dev_class);
out_unreg_chrdev:
        unregister_chrdev(I2C_MAJOR, "i2c");
out:
        printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
        return res;
}

module_init(i2c_dev_init);

static struct i2c_driver i2cdev_driver = {
        .driver = {
                .name   = "dev_driver",
        },
        .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);
        if (IS_ERR(i2c_dev))
                return PTR_ERR(i2c_dev);

        /* 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);
        if (IS_ERR(i2c_dev->dev)) {
                res = PTR_ERR(i2c_dev->dev);
                goto error;
        }
        res = device_create_file(i2c_dev->dev, &dev_attr_name);
        if (res)
                goto error_destroy;

        pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",

                  adap->name, adap->nr);
        return 0;
error_destroy:
        device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error:
        return_i2c_dev(i2c_dev);
        return res;
}

static int i2cdev_detach_adapter(struct i2c_adapter *adap)
{
        struct i2c_dev *i2c_dev;

        i2c_dev = i2c_dev_get_by_minor(adap->nr);
        if (!i2c_dev) /* attach_adapter must have failed */
                return 0;

        device_remove_file(i2c_dev->dev, &dev_attr_name);
        return_i2c_dev(i2c_dev);
        device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));

        pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
        return 0;
}

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 ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
                            loff_t *offset)
{
        char *tmp;
        int ret;

        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;

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

        ret = i2c_master_recv(client,tmp,count);
        if (ret >= 0)
                ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
        kfree(tmp);
        return ret;

}

int i2c_master_recv(struct i2c_client *client, char *buf ,int count)// driver/i2c/i2c-core.c
{
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
        int ret;

        msg.addr = client->addr;
        msg.flags = client->flags & I2C_M_TEN;
        msg.flags |= I2C_M_RD;
        msg.len = count;
        msg.buf = 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;
}

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
        unsigned long orig_jiffies;
        int ret, try;

        /* REVISIT the fault reporting model here is weak:
         *
         *  - When we get an error after receiving N bytes from a slave,
         *    there is no way to report "N".
         *
         *  - When we get a NAK after transmitting N bytes to a slave,
         *    there is no way to report "N" ... or to let the master
         *    continue executing the rest of this combined message, if
         *    that's the appropriate response.
         *
         *  - When for example "num" is two and we successfully complete
         *    the first message but get an error part way through the
         *    second, it's unclear whether that should be reported as
         *    one (discarding status on the second message) or errno
         *    (discarding status on the first one).
         */

        if (adap->algo->master_xfer) {

#ifdef DEBUG
                for (ret = 0; ret < num; ret++) {
                        dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
                                "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
                                ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
                                (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
                }
#endif

                if (in_atomic() || irqs_disabled()) {
                        ret = mutex_trylock(&adap->bus_lock);
                        if (!ret)
                                /* I2C activity is ongoing. */
                                return -EAGAIN;
                } else {
                        mutex_lock_nested(&adap->bus_lock, adap->level);
                }

                /* Retry automatically on arbitration loss */
                orig_jiffies = jiffies;
                for (ret = 0, try = 0; try <= adap->retries; try++) {
                        ret = adap->algo->master_xfer(adap, msgs, num);

                        if (ret != -EAGAIN)
                                break;
                        if (time_after(jiffies, orig_jiffies + adap->timeout))
                                break;
                }
                mutex_unlock(&adap->bus_lock);

                return ret;
        } else {
                dev_dbg(&adap->dev, "I2C level transfers not supported\n");
                return -EOPNOTSUPP;
        }
}

 

三、


 

 

 



 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值