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