动手写一个i2c设备驱动(2)

struct i2c_adapter
--428-->这个i2c控制器需要的控制算法, 其中最重要的成员是master_xfer()接口, 这个接口是硬件相关的, 里面的操作都是基于具体的SoCi2c寄存器的, 它将完成将数据发送到物理i2c控制器的"最后一公里"
--436-->表示这个一个device, 会挂接到内核中的链表中来管理, 其中的
--443-->这个节点将一个i2c_adapter对象和它所属的i2c_client对象以及相应的i2c_driver对象连接到一起

下面是2个i2c-core.c提供的i2c_adapter直接相关的操作API, 通常也不需要设备驱动开发中使用,

i2c_add_adapter

这个API可以将一个i2c_adapter类型的对象注册到内核中, 源码我就不贴了, 下面是他们的调用关系,我们可以从中看到一个adapter对象和系统中的i2c_driver对象以及i2c_client对象的匹配流程。
首先,我们在驱动中构造一个i2c_adapter对象的时候,对其中的相关域进行初始化,这里我们最关心它的父设备

//drivers/i2c/buses/i2c-s3c2410.c 1072 static int s3c24xx_i2c_probe(struct platform_device *pdev) 1073 { 1140 i2c->adap.dev.parent = &pdev->dev; 1210 }

得到了这样一个i2c_adapter对象,我们就可以调用这个API将它注册到内核,调用关系如下:

i2c_add_adapter()
1        └──i2c_register_adapter(adapter)
2                ├──adap->dev.bus = &i2c_bus_type;
3                ├──adap->dev.type = &i2c_adapter_type;
4                │        └──i2c_adapter_attr_groups
5                │                └── i2c_adapter_attr_group
6                │                        └── i2c_adapter_attrs
7                │                                └── &dev_attr_new_device.attr
8                │                                        └──DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device);
9                │                                                └──i2c_sysfs_new_device()
10               │                                                                  └──list_add_tail(&client->detected, &adap->userspace_clients);
11               └──device_register(&adap-dev);
12                        ├──device_initialize(dev);
13                        │        ├──/* /sys/devices/ /
14                        │        ├──struct kset devices_kset;
15                        │        ├──dev->kobj.kset = devices_kset;
16                        │        ├──kobject_init(&dev->kobj, &device_ktype);
17                        │        └──set_dev_node(dev, -1);
18                        └──device_add(dev);
19                                ├──parent=get_device(dev->parent);
20                                ├──kobj = get_device_parent(dev, parent);
21                                │        └──return &parent->kobj;
22                                ├──dev->kobj.parent = kobj;
23                                ├──set_dev_node(dev, dev_to_node(parent));
24                                ├──kobject_add(&dev->kobj, dev->kobj.parent, NULL);
25                                │        ├──kobject_add_varg(kobj, parent, fmt, args);
26                                │        ├──kobj->parent = parent;
27                                │        ├──kobject_add_internal(kobj);
28                                │        ├──parent = kobject_get(kobj->parent);
29                                │        ├──kobj_kset_join(kobj);
30                                │        │        ├──kset_get(kobj->kset)
31                                │        │        └──list_add_tail(&kobj->entry, &kobj->kset->list);
32                                │        ├──kobj->parent = parent;
33                                │        └──create_dir(kobj);
34                                ├──device_create_file(dev, &dev_attr_uevent);
35                                ├──device_create_sys_dev_entry(dev);
36                                ├──devtmpfs_create_node(dev);
37                                ├──device_add_class_symlinks(dev);
38                                ├──device_add_attrs(dev);
39                                ├──bus_add_device(dev);
40                                ├──bus_probe_device(dev);
41                                ├──klist_add_tail(&dev->p->knode_parent,&parent->p->klist_children);
42                                └──klist_add_tail(&dev->knode_class,&dev->class->p->klist_devices);

调用关系就是这样了,下面我简单解释一下这个树

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/95a26e3a7df27d38ce2c2e697be33148.html