请选择 进入手机版 | 继续访问电脑版

环信

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: mmap uikit gcc
查看: 336|回复: 4

14. 设备驱动模型 Bus Device Driver

  [复制链接]

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
发表于 2015-10-3 11:52:04 | 显示全部楼层 |阅读模式
本帖最后由 cat 于 2015-12-22 16:30 编辑

设备模型

元素:总线 驱动 设备

总线
    是处理器和设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟“platform”总线。
    在Linux 设备模型中, 总线由bus_type 结构表示, 定义在<linux/Device.h>
        struct bus_type {
            const char *name; /*总线名称*/
            struct bus_attribute *bus_attrs; /*总线属性*/
            struct device_attribute *dev_attrs; /*设备属性*/
            struct driver_attribute *drv_attrs; /*驱动属性*/
            int (*match)(struct device *dev, struct device_driver *drv);
            int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
            int (*probe)(struct device *dev);
            int (*remove)(struct device *dev);
            void (*shutdown)(struct device *dev);
            int (*suspend)(struct device *dev, pm_message_t state);
            int (*suspend_late)(struct device *dev, pm_message_t state);
            int (*resume_early)(struct device *dev);
            int (*resume)(struct device *dev);
            struct dev_pm_ops *pm;
            struct bus_type_private *p;
        }
   
    总线注册/删除   
        总线的注册使用:bus_register(struct bus_type * bus)
            若成功,新的总线将被添加进系统,并可在sysfs 的/sys/bus 下看到。
        总线的删除使用:
            void bus_unregister(struct bus_type *bus)   
            
    总线方法        
        int (*match)(struct device * dev, struct device_driver * drv)
            当一个新设备或者驱动被添加到这个总线时,该方法被调用。
            用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。
        int (*uevent)(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
            在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量。        
            
    总线属性
        由结构bus_attribute 描述,定义如下:
            struct bus_attribute {
                struct attribute attr;
                ssize_t (*show)(struct bus_type *, char * buf);
                ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
            }
        
        int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
            创建属性
        void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
            删除属性
        
        /* 自动创建show_bus_version,通过BUS_ATTR,为何?????????
        bus_create_file(&my_bus_type, &bus_attr_version)
        static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
        #define BUS_ATTR(_name, _mode, _show, _store)    \
        struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
        */
   

设备描述
    Linux 系统中的每个设备由一个struct device 描述:
    struct device {
        ………………………………
        struct kobject kobj;
        char bus_id[BUS_ID_SIZE]; /*在总线上唯一标识该设备的字符串*/
        struct bus_type *bus; /* 设备所在总线*/
        struct device_driver *driver; /*管理该设备的驱动*/
        void *driver_data; /*该设备驱动使用的私有数据成员*
        struct klist_node knode_class;
        struct class *class;
        struct attribute_group **groups;
        void (*release)(struct device *dev);
    }   
   
    设备注册
        int device_register(struct device *dev)
            注册设备
        void device_unregister(struct device *dev)
            注销设备
    **一条总线也是个设备,也必须按设备注册**        
   
    设备属性
    由struct 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);
    }   
    int device_create_file(struct device *device, struct device_attribute * entry)
        创建属性
    void device_remove_file(struct device * dev, struct device_attribute * attr)
        删除属性   
    /*    DEVICE_ATTR */
        
        
驱动程序
    驱动描述由struct device_driver 描述:
    struct device_driver {
        const char *name; /*驱动程序的名字( 体现在sysfs 中)*/
        struct bus_type *bus; /*驱动程序所在的总线*/
        struct module *owner;
        const char *mod_name;
        int (*probe) (struct device *dev);
        int (*remove) (struct device *dev);
        void (*shutdown) (struct device *dev);
        int (*suspend) (struct device *dev, pm_message_t state);
        int (*resume) (struct device *dev);
        struct attribute_group **groups;
        struct dev_pm_ops *pm;
        struct driver_private *p;
    }   

    驱动注册/注销
    int driver_register(struct device_driver *drv)
        注册驱动
    void driver_unregister(struct device_driver *drv)
        注销驱动   

    驱动属性
    使用struct driver_attribute 来描述:
        struct driver_attribute {
            struct attribute attr;
            ssize_t (*show)(struct device_driver *drv,
            char *buf);
            ssize_t (*store)(struct device_driver *drv,
            const char *buf, size_t count);
        }

    int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
        创建属性
    void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
        删除属性
    /*    DRIVER_ATTR */

回复

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2015-10-3 11:53:11 | 显示全部楼层
本帖最后由 cat 于 2015-12-22 16:31 编辑

bus_basic.c
  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/string.h>

  6. MODULE_AUTHOR("Dick Tsang");
  7. MODULE_LICENSE("Dual BSD/GPL");

  8. static char *Version = "$Revision: 1.9 $";

  9. /*
  10. 当一个新设备或者驱动被添加到这个总线时,该方法被调用。
  11. 用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。
  12. */
  13. static int my_match(struct device *dev, struct device_driver *driver)
  14. {
  15.     return !strncmp(dev->kobj.name, driver->name, strlen(driver->name));
  16. }

  17. static void my_bus_release(struct device *dev)
  18. {
  19.     printk(KERN_DEBUG "my bus release\n");
  20. }
  21.    
  22. struct device my_bus = {
  23.     .init_name   = "my_bus0", //.bus_id   = "my_bus0",
  24.     .release  = my_bus_release
  25. };

  26. /*
  27. 在Linux 设备模型中, 总线由bus_type 结构表示, 定义在<linux/Device.h>
  28. */
  29. struct bus_type my_bus_type = {
  30.     .name = "my_bus", //总线名称
  31.     .match = my_match,
  32.     /*
  33.     int (*match)(struct device *dev, struct device_driver *drv);
  34.          struct bus_attribute *bus_attrs; //总线属性
  35.          struct device_attribute *dev_attrs; //设备属性
  36.          struct driver_attribute *drv_attrs; //驱动属性
  37.     */
  38. };

  39. EXPORT_SYMBOL(my_bus);
  40. EXPORT_SYMBOL(my_bus_type);


  41. /*
  42. * Export a simple attribute.
  43. */
  44. static ssize_t show_bus_version(struct bus_type *bus, char *buf)
  45. {
  46.     return snprintf(buf, PAGE_SIZE, "%s\n", Version);
  47. }

  48. static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);


  49. static int __init my_bus_init(void)
  50. {
  51.     int ret;
  52.         
  53.         /*注册总线
  54.         新的总线将被添加进系统,并可在sysfs 的/sys/bus 下看到
  55.         */
  56.     ret = bus_register(&my_bus_type);
  57.     if (ret)
  58.         return ret;
  59.         
  60.     /*创建属性文件*/   
  61.     /*
  62.         自动创建show_bus_version,通过BUS_ATTR
  63.         bus_create_file(&my_bus_type, &bus_attr_version)
  64.         static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
  65.         #define BUS_ATTR(_name, _mode, _show, _store)    \
  66.         struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
  67.         */
  68.     if (bus_create_file(&my_bus_type, &bus_attr_version))
  69.         printk(KERN_NOTICE "Fail to create version attribute!\n");
  70.    
  71.     /*注册总线设备*/
  72.     ret = device_register(&my_bus);
  73.     if (ret)
  74.         printk(KERN_NOTICE "Fail to register device:my_bus!\n");
  75.         
  76.     return ret;
  77. }

  78. static void my_bus_exit(void)
  79. {
  80.     device_unregister(&my_bus);
  81.     bus_unregister(&my_bus_type);
  82. }

  83. module_init(my_bus_init);
  84. module_exit(my_bus_exit);
复制代码
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2015-12-22 16:32:24 | 显示全部楼层
bus.c
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/device.h>

  5. MODULE_LICENSE("GPL");

  6. int my_match(struct device *dev, struct device_driver *drv)
  7. {
  8.     return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
  9. }  


  10. struct bus_type my_bus_type = {
  11.         .name = "my_bus",
  12.         .match = my_match,
  13.         };
  14.        
  15. EXPORT_SYMBOL(my_bus_type);

  16. int my_bus_init()
  17. {
  18.         int ret;
  19.        
  20.         ret = bus_register(&my_bus_type);
  21.        
  22.         return ret;

  23. }

  24. void my_bus_exit()
  25. {
  26.         bus_unregister(&my_bus_type);
  27. }


  28. module_init(my_bus_init);
  29. module_exit(my_bus_exit);
复制代码
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2015-12-22 16:33:13 | 显示全部楼层
device.c
  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>

  5. MODULE_LICENSE("GPL");

  6. extern struct bus_type my_bus_type;

  7. static void my_dev_release(struct device *dev)
  8. {
  9.        
  10. }

  11. struct device my_dev = {
  12.      .init_name = "my_dev",
  13.      .bus = &my_bus_type,       
  14.      .release = my_dev_release,
  15. };

  16. static int my_device_init(void)
  17. {
  18.         int ret;
  19.      ret = device_register(&my_dev);
  20.      return ret;
  21.      
  22. }


  23. static void my_device_exit(void)
  24. {
  25.         device_unregister(&my_dev);
  26. }

  27. module_init(my_device_init);
  28. module_exit(my_device_exit);
复制代码
回复 支持 反对

使用道具 举报

21

主题

43

帖子

140

积分

注册会员

Rank: 2

积分
140
 楼主| 发表于 2015-12-22 16:33:33 | 显示全部楼层
driver.c
  1. #include <linux/device.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>

  5. MODULE_LICENSE("GPL");

  6. extern struct bus_type my_bus_type;

  7. int my_probe(struct device *dev)
  8. {
  9.     printk("driver found the device it can handle!\n");
  10.     return 0;
  11. }

  12. struct device_driver my_driver = {
  13.     .name = "my_dev",
  14.     .bus = &my_bus_type,       
  15.     .probe = my_probe,
  16. };

  17. static int my_driver_init(void)
  18. {
  19.         int ret;
  20.        
  21.         ret = driver_register(&my_driver);
  22.        
  23.         return ret;
  24. }


  25. static void my_driver_exit(void)
  26. {
  27.         driver_unregister(&my_driver);       
  28. }


  29. module_init(my_driver_init);
  30. module_exit(my_driver_exit);
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|环信 Glofty.com ( 粤ICP备15084637号 )

GMT+8, 2017-2-28 15:48 , Processed in 0.227624 second(s), 21 queries .

快速回复 返回顶部 返回列表