从APP层----设备驱动层----核心层------
APP:fd = open("/dev/i2c-1", O_RDWR);
VFS: sys_open
i2c-dev.c: i2c_dev_init()
执行i2cdev_fops的open *** 作即:i2cdev_open();
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; i2c_dev = i2c_dev_get_by_minor(minor); if (!i2c_dev) return -ENODEV; //获取适配器 adap = i2c_get_adapter(i2c_dev->adap->nr); if (!adap) return -ENODEV; client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { i2c_put_adapter(adap); return -ENOMEM; } snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); client->adapter = adap; //指定client属于哪个适配器 file->private_data = client; return 0; }
=========================================================================
APP: ioctl(fd, I2C_SLAVE, device_addr)
VFS: sys_ioctl
i2c-dev.c:执行i2cdev_fops的unlocked_ioctl *** 作即:i2cdev_ioctl();
static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { // 获取client属性 struct i2c_client *client = file->private_data; unsigned long funcs; dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lxn", cmd, arg); switch (cmd) { case I2C_SLAVE: case I2C_SLAVE_FORCE: if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) return -EINVAL; if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) return -EBUSY; client->addr = arg; //指定设备地址 return 0; case I2C_TENBIT: //设置10 bit地址模式 if (arg) client->flags |= I2C_M_TEN; else client->flags &= ~I2C_M_TEN; return 0; case I2C_PEC: //设置传输后增加PEC标志 if (arg) client->flags |= I2C_CLIENT_PEC; else client->flags &= ~I2C_CLIENT_PEC; return 0; case I2C_FUNCS: //获取函数支持 funcs = i2c_get_functionality(client->adapter); return put_user(funcs, (unsigned long __user *)arg); case I2C_RDWR: //读取和接收数据,后面讲述 return i2cdev_ioctl_rdrw(client, arg); case I2C_SMBUS: //smbus协议数据传输,后面讲述 return i2cdev_ioctl_smbus(client, arg); case I2C_RETRIES: //设置重试次数 client->adapter->retries = arg; break; case I2C_TIMEOUT: //设置超时时间 client->adapter->timeout = msecs_to_jiffies(arg * 10); break; default: return -ENOTTY; } return 0; }
=========================================================================
APP:write(fd ,wbuf, 2)
VFS: sys_write
i2c-dev.c:执行i2cdev_fops的write *** 作即:i2cdev_write();
static ssize_t i2cdev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { int ret; char *tmp; struct i2c_client *client = file->private_data; if (count > 8192) count = 8192; tmp = memdup_user(buf, count); if (IS_ERR(tmp)) return PTR_ERR(tmp); 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是i2c-core.c核心层的函数,即代表到i2c-core层
int i2c_master_send(struct i2c_client *client,const char *buf ,int count) { int ret; struct i2c_adapter *adap=client->adapter; // 获取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 (eg: 1 msg transmitted), return bytes number transmitted, else error code. return (ret == 1) ? count : ret; // 如果发送成功就返回字节数 }
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
{
int ret;
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)
return -EAGAIN;
} else {
mutex_lock_nested(&adap->bus_lock, adap->level);
}
ret = adap->algo->master_xfer(adap,msgs,num);
mutex_unlock(&adap->bus_lock);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported/n");
return -ENOSYS;
}
}
通过i2c_transfer的adap->algo->master_xfer(adap,msgs,num);调用到i2c-s3c2410.c文件的函数,进而调用到总线驱动层。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)