1.device的结构:
struct device
{
struct klist klist_children; //设备列表中的子列表
struct klist_node knode_parent; //兄弟节点
struct klist_node knode_driver; //驱动程序节点
struct klist_node knode_bus; //总线节点
struct device* parent; //父设备节点,即,当前设备所附着到的设备
struct kobject kobj; //代表当前设备,并连接它到层次中的kobject
char bus_id[BUS_ID_SIZE]; //唯一确定这个总线上的设备的字符串,即,总线上设备的位置
struct device_attribute uevent_attr;
struct device_attribute* devt_attr;
struct semaphore sem; //信号量
struct bus_type* bus; //总线类型,即,哪种总线
struct device_driver* driver; //这个设备所使用的驱动程序
void* driver_data; //一个可能被设备驱动程序所使用的私有数据
void* platform_data; /* Platform specific data, device core doesn't touch it */
void* firmware_data; /* Firmware specific data (e.g. ACPI, BIOS data),reserved for device core*/
struct dev_pm_info power;
u64* dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem* dma_mem; /* internal for coherent mem override */
struct list_head node; /* class_device migration path */
struct class* class; /* optional */
dev_t devt; /* dev_t, creates the sysfs "dev" */
void (*release)(struct device* dev); //释放设备的函数
};
//重点看一下私有属性结构
struct device_private {
struct klist klist_children; //子集结构
struct klist_node knode_parent; //父级挂接点
struct klist_node knode_driver; //driver挂接点
struct klist_node knode_bus; //bus挂接点
void *driver_data;
struct device *device; //回指
};
2.device的注册
int device_register(struct device *dev)
{
device_initialize(dev); //初始化dev
return device_add(dev); //添加dev
}
先看一下device_initialize(dev)
void device_initialize(struct device *dev)
{
dev->kobj.kset = devices_kset; //可见device和bus都有其起始的kset,而driver没有
kobject_init(&dev->kobj, &device_ktype); //初始化kobj并建立层次关系以及属性文件
INIT_LIST_HEAD(&dev->dma_pools); //是放到了总的device文件目录下面
mutex_init(&dev->mutex);
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
device_pm_init(dev);
set_dev_node(dev, -1);
}
再来看一下device_add(dev)
int device_add(struct device *dev)
{
struct device *parent = NULL;
struct class_interface *class_intf;
dev = get_device(dev);
if (!dev->p) {
error = device_private_init(dev); //初始化dev的私有成员,及其链表操作函数
}
if (dev->init_name) {
dev_set_name(dev, "%s", dev->init_name); //设置名字,给kobj
dev->init_name = NULL;
}
if (!dev_name(dev)) { //名字为空出错退出
error = -EINVAL;
goto name_error;
}
parent = get_device(dev->parent); //返回父节点,如果有返回,没有返回NULL
setup_parent(dev, parent);
if (parent)
set_dev_node(dev, dev_to_node(parent));
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); //初始化kobj与其父节点的连接
if (platform_notify)
platform_notify(dev);
error = device_create_file(dev, &uevent_attr); //产生属性文件
if (MAJOR(dev->devt)) {
error = device_create_file(dev, &devt_attr); //在sys下产生dev属性文件
error = device_create_sys_dev_entry(dev);
devtmpfs_create_node(dev);
}
error = device_add_class_symlinks(dev);
error = device_add_attrs(dev); //增加属性文件
error = bus_add_device(dev); //把device的bus节点挂到bus的设备节点上
error = dpm_sysfs_add(dev);
device_pm_add(dev);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_probe_device(dev); //匹配driver
if (parent)
klist_add_tail(&dev->p->knode_parent, //把该设备的节点挂到其父节点的链表
&parent->p->klist_children);
if (dev->class) {
mutex_lock(&dev->class->p->class_mutex);
/* tie the class to the device */
klist_add_tail(&dev->knode_class,
&dev->class->p->class_devices);
/* notify any interfaces that the device is here */
list_for_each_entry(class_intf,
&dev->class->p->class_interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
mutex_unlock(&dev->class->p->class_mutex);
}
}
重点看一下bus_probe_device匹配driver以及初始化过程
void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
int ret;
if (bus && bus->p->drivers_autoprobe) { //设置了自动匹配初始化那么就开始匹配
ret = device_attach(dev);
WARN_ON(ret < 0);
}
}
继续device_attach
int device_attach(struct device *dev)
{
int ret = 0;
device_lock(dev);
if (dev->driver) { //默认指定了driver就直接绑定
ret = device_bind_driver(dev);
if (ret == 0)
ret = 1;
else {
dev->driver = NULL;
ret = 0;
}
} else { //没有指定就进行遍历匹配
pm_runtime_get_noresume(dev);
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_runtime_put_sync(dev);
}
device_unlock(dev);
return ret;
}
再来看device_bind_driver分支
int device_bind_driver(struct device *dev)
{
int ret;
ret = driver_sysfs_add(dev);
if (!ret)
driver_bound(dev); //主要是完成了将私有成员的driver节点挂到
return ret; //了driver的设备链表
}
先看bus_for_each_drv分支
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *))
{
struct klist_iter i;
struct device_driver *drv;
int error = 0;
if (!bus)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_drivers, &i, //和driver遍历device类似,从头开始遍历bus的driver链表
start ? &start->p->knode_bus : NULL); //发现一个driver就调用fn即__device_attach进行匹配
while ((drv = next_driver(&i)) && !error)
error = fn(drv, data);
klist_iter_exit(&i);
return error;
}
最后来看一下__device_attach这个函数
static int __device_attach(struct device_driver *drv, void *data)
{
struct device *dev = data;
if (!driver_match_device(drv, dev))
return 0;
return driver_probe_device(drv, dev);
}
3.设备属性:
struct device_attribute
{
struct attribute attr;
ssize_t (*show)(struct device* dev, struct device_attribute* attr, char* buf);
ssize_t (*store)(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
};
int device_create_file(struct device* dev, struct device_attribute* attr):为指定设备添加属性;
void device_remove_file(struct device* dev, struct device_attribute* attr):删除指定设备上的指定属性;