您的位置:首页 > 运维架构 > Linux

Linux驱动之设备模型(5)

2016-05-19 16:54 471 查看


Linux驱动之设备模型(5)

 

(2013-02-21 11:11:20)


转载▼

标签: 


设备模型

 


linux

分类: 设备模型

原文地址: http://blog.csdn.net/hsly_support/article/details/7366595

6.设备

6.1  设备

l  Linux设备模型中每一个设备用device结构来表示

struct device {

         struct device             *parent;  

         struct device_private       *p;  

         struct kobject  kobj;         

         const char                  *init_name;

         const struct device_type  *type; 

         struct bus_type        *bus;   

         struct device_driver *driver;  

         void           *platform_data;     

         dev_t                           devt;        

 

         struct klist_node      knode_class; 

         struct class                *class;      

         const struct attribute_group **groups;

         void  (*release)(structdevice *dev); 

};

 

6.2 设备属性

l  设备属性由device_attribute来表示

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

};

DEVICE_ATTR(_name,_mode, _show, _store)

 

l  属性操作

    n  添加属性

    int  device_create_file(struct device *device,

                                               conststruct
device_attribute *entry);

    n  删除属性

    void  device_remove_file(struct device *dev,

                                                const
struct device_attribute*attr);

 

6.3  设备注册和注销

l  设备注册和注销

int  device_register(struct device *dev);

void  device_unregister(struct device *dev);

 

l  设备注册分析

注册函数由初始化设备(device_initialize)和添加设备到系统(device_add)中两步构成,主要分析一下第二步

n  device_add,添加设备

int device_add(structdevice *dev)

{

         struct device *parent = NULL;

         struct class_interface *class_intf;

         int error = -EINVAL;

        

        

         dev = get_device(dev);

 

        

         if (dev->init_name) {

                   dev_set_name(dev,"%s", dev->init_name);

                   dev->init_name = NULL;

         }

 

        

         parent = get_device(dev->parent);

         setup_parent(dev, parent);

 

        

         error = kobject_add(&dev->kobj,dev->kobj.parent, NULL);

 

                  

         error = device_create_file(dev,&uevent_attr);

 

        

         if (MAJOR(dev->devt)) {

                   error = device_create_file(dev,&devt_attr);

                  }

 

        

         error = device_add_class_symlinks(dev);

         error = device_add_attrs(dev);

 

        

         error = bus_add_device(dev);

 

                  

         kobject_uevent(&dev->kobj,KOBJ_ADD);

 

        

         bus_probe_device(dev);

 

        

         if (parent)

                   klist_add_tail(&dev->p->knode_parent,

                                   &parent->p->klist_children);

 

        

         if (dev->class) {

                  

                   klist_add_tail(&dev->knode_class,

                                  &dev->class->p->klist_devices);

 

                  

                   list_for_each_entry(class_intf,

                                        &dev->class->p->class_interfaces,
node)

                            if(class_intf->add_dev)

                                     class_intf->add_dev(dev,class_intf);

         }

}

 

n  bus_add_device

int  bus_add_device(struct device *dev)

{

        

         struct bus_type *bus =bus_get(dev->bus);

 

         if (bus) {

                  

                   error = device_add_attrs(bus,dev);

                   error =sysfs_create_link(&bus->p->devices_kset->kobj,

                                                        &dev->kobj,dev_name(dev));

                   error =sysfs_create_link(&dev->kobj,

                                     &dev->bus->p->subsys.kobj,"subsystem");

                  

                   klist_add_tail(&dev->p->knode_bus,&bus->p->klist_devices);

         }

}

 

n  bus_probe_device,为设备探测相应的驱动

bus_probe_device()->device_attach()

int  device_attach(struct device *dev)

{

         if (dev->driver) {

                  

                   ret =device_bind_driver(dev);

         } else {

                  

                   ret = bus_for_each_drv(dev->bus, NULL, dev,__device_attach);

         }

out_unlock:

         device_unlock(dev);

         return ret;

}

__device_attach()->driver_probe_device()->really_probe()->bus->probe()->drv->probe()  总线中定义的probe函数会优先执行,如果总线中没有定义probe才会执行驱动中定义的probe

 

 

 

6.4  实例解析

创建一个设备和它的属性version,并将此设备挂接到之前创建的总线上

 

#include

#include

#include

#include

 

extern struct bus_type scbus_type;

extern struct device scbus;

 

static char *Version = "revision1.0";

 

 

void screlease(struct device *dev)

{

         printk("scbusrelease\n");

}

 

struct device scdevice = {

         .parent     = &scbus,          

         .init_name        = "scdevice0", 

         .bus = &scbus_type,       

         .release   = screlease,

};

 

 

static ssize_t show_device_version(struct  device *dev,

                            struct  device_attribute *attr, char *buf)

{

         return  sprintf(buf, "%s\n", Version);

}

DEVICE_ATTR(version, 0ow_device_version, NULL);

 

 

static int __init scdevice_init(void)

{

         int ret;

        

         ret= device_register(&scdevice);

         if(ret)

                   return  ret;

 

        

         ret= device_create_file(&scdevice, &dev_attr_version);

         if(ret)

                   goto  err_create;

         printk("Createa scdevice");

         return  0;

 

err_create:

         device_unregister(&scdevice);

         return  ret;

}

 

static void __exit scdevice_exit(void)

{

         device_remove_file(&scdevice,&dev_attr_version);

         device_unregister(&scdevice);

         printk("Removea scdevice");

}

 

module_init(scdevice_init);

module_exit(scdevice_exit);

 

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("CJOK");

 

试验结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: