Linux设备模型(总线、设备、驱动程序和类)之四:class_register

来源:互联网 发布:保税货物需要上传数据 编辑:程序博客网 时间:2024/06/09 22:47
类是一个设备的高层视图,它抽象出了底层的实现细节,从而允许用户空间使用设备所提供的功能,而不用关心设备是如何连接和工作的。类成员通常由上层代码所控制,而无需驱动的明确支持。但有些情况下驱动也需要直接处理类。
      几乎所有的类都显示在/sys/class目录中,可以通过ls -l /sys/class来显示。出于历史的原因,有一个例外:块设备显示在/sys/block目录中。在许多情况,类子系统是向用户空间导出信息的最好方法。当类子系统创建一个类时,它将完全拥有这个类,根本不用担心哪个模块拥有那些属性,而且信息的表示也比较友好。为了管理类,驱动程序核心导出了一些接口,其目的之一是提供包含设备号的属性以便自动创建设备节点,所以udev的使用离不开类。类函数和结构与设备模型的其他部分遵循相同的模式,可与前三篇文章类比
(1)管理类的接口和注册注销函数
     类由 struct class 的结构体来定义:
struct class {
     const char  *name; *每个类需要一个唯一的名字, 它将显示在 /sys/class 中*/
     struct module  *owner;

     struct class_attribute  *class_attrs;
     struct device_attribute  *dev_attrs;
     struct kobject   *dev_kobj;

     int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);

     void (*class_release)(struct class *class); /* 删除类本身的函数 */
     void (*dev_release)(struct device *dev);
   
     int (*suspend)(struct device *dev, pm_message_t state);
     int (*resume)(struct device *dev);

     struct pm_ops *pm;
     struct class_private *p;
};

     /*类注册函数:*/
int class_register(struct class *cls);
void class_unregister(struct class *cls);

/*类属性的接口:*/
struct class_attribute {
     struct attribute attr;
     ssize_t (*show)(struct class *cls, char *buf);
     ssize_t (*store)(struct class *cls, const char *buf, size_t count);
};

CLASS_ATTR(_name,_mode,_show,_store);
int class_create_file(struct class *cls, const struct class_attribute *attr);
void class_remove_file(struct class *cls, const struct class_attribute *attr);、
(2)类设备,类存在的真正目的是给作为类成员的各个设备提供一个容器,成员由struct class_device 来表示,暂没用到。
(3)类接口
      类子系统有一个 Linux 设备模型的其他部分找不到的附加概念,称为“接口”,可将它理解为一种设备加入或离开类时获得信息的触发机制,结构体如下:
struct class_interface {
      struct list_head node;
      struct class  *class;

      int (*add_dev)  (struct device *, struct class_interface *);
      void (*remove_dev) (struct device *, struct class_interface *);
};
/*注册或注销接口的函数:*/
int class_interface_register(struct class_interface *class_intf);
void class_interface_unregister(struct class_interface *class_intf);
/*一个类可注册多个接口*/

        设定class的好处:设备驱动一般在注册的时候都会调用此类class的一些函数,主要作用就是在sys目录里面创建一些节点,比如cd到/sys/class下面可以看到这一类的设备,与这个相关的就是一些kobjects。当然对于一个新设备,可以注册进一个class也可以不注册进去,如果存在对应class的话注册进去更好。

(4)struct class的创建

        很多时候,我们需要用到attr属性创建show/store属性时,缺少struct device对象。那么我们需要通过一系列操作来间接的达到目的,举例方法如下:

struct class *firmware_class;
struct device *firmware_cmd_dev;

         在模块驱动的probe函数中,比如在int tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)中,

firmware_class = class_create(THIS_MODULE, client->name);       //以name创建class
if(IS_ERR(firmware_class))
  {
          printk("Failed to create class(firmware)!\n");
  }

firmware_cmd_dev = device_create(firmware_class,NULL, 0, NULL, "device");     //在class的基础上创建device为名的结构体
if(IS_ERR(firmware_cmd_dev))
  {
          printk("Failed to create device(firmware_cmd_dev)!\n");
  }

之后即可通过firmware_cmd_dev作为struct device指针对象,用device_create_file来创建属性。属性路径如下: /sys/class/mtk-tpd/device/。

参考原文:http://blog.csdn.net/funy_liu/archive/2010/02/25/5322040.aspx

原创粉丝点击