]> git.neil.brown.name Git - history.git/commitdiff
driverfs: add glue layer for drivers to export attributes via driverfs
authorPatrick Mochel <mochel@osdl.org>
Fri, 2 Aug 2002 06:40:31 +0000 (23:40 -0700)
committerPatrick Mochel <mochel@osdl.org>
Fri, 2 Aug 2002 06:40:31 +0000 (23:40 -0700)
This defines struct driver_attribute so device drivers themselves can export attributes
via driverfs.

The macro DRIVER_ATTR is defined for declaring the attributes.

driver_{create,remove}_file are implemented for creating and removing files.

drivers/base/fs/driver.c
include/linux/device.h

index 9da487f16acdbf63ec62f05e536f283c33defdb1..93e0e6897d74b23275dd743e804af4070c00f613 100644 (file)
@@ -1,6 +1,84 @@
 #include <linux/device.h>
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/err.h>
 #include "fs.h"
 
+#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
+
+#define to_drv(d) container_of(d, struct device_driver, dir)
+
+
+/* driverfs ops for device attribute files */
+
+static int
+drv_attr_open(struct driver_dir_entry * dir)
+{
+       struct device_driver * drv = to_drv(dir);
+       get_driver(drv);
+       return 0;
+}
+
+static int
+drv_attr_close(struct driver_dir_entry * dir)
+{
+       struct device_driver * drv = to_drv(dir);
+       put_driver(drv);
+       return 0;
+}
+
+static ssize_t
+drv_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
+             char * buf, size_t count, loff_t off)
+{
+       struct driver_attribute * drv_attr = to_drv_attr(attr);
+       struct device_driver * drv = to_drv(dir);
+       ssize_t ret = 0;
+
+       if (drv_attr->show)
+               ret = drv_attr->show(drv,buf,count,off);
+       return ret;
+}
+
+static ssize_t
+drv_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
+              const char * buf, size_t count, loff_t off)
+{
+       struct driver_attribute * drv_attr = to_drv_attr(attr);
+       struct device_driver * drv = to_drv(dir);
+       ssize_t ret = 0;
+
+       if (drv_attr->store)
+               ret = drv_attr->store(drv,buf,count,off);
+       return ret;
+}
+
+static struct driverfs_ops drv_attr_ops = {
+       open:   drv_attr_open,
+       close:  drv_attr_close,
+       show:   drv_attr_show,
+       store:  drv_attr_store,
+};
+
+int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
+{
+       int error;
+       if (get_driver(drv)) {
+               error = driverfs_create_file(&attr->attr,&drv->dir);
+               put_driver(drv);
+       } else
+               error = -EINVAL;
+       return error;
+}
+
+void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
+{
+       if (get_driver(drv)) {
+               driverfs_remove_file(&drv->dir,attr->attr.name);
+               put_driver(drv);
+       }
+}
+
 /**
  * driver_make_dir - create a driverfs directory for a driver
  * @drv:       driver in question
@@ -8,6 +86,8 @@
 int driver_make_dir(struct device_driver * drv)
 {
        drv->dir.name = drv->name;
+       drv->dir.ops = &drv_attr_ops;
+
        return device_create_dir(&drv->dir,&drv->bus->driver_dir);
 }
 
@@ -16,3 +96,5 @@ void driver_remove_dir(struct device_driver * drv)
        driverfs_remove_dir(&drv->dir);
 }
 
+EXPORT_SYMBOL(driver_create_file);
+EXPORT_SYMBOL(driver_remove_file);
index 9707eca4331f5049d299ac342db986312132911a..9706d94ff7b6008190b33bd4101187eda17823da 100644 (file)
@@ -142,6 +142,24 @@ extern int driver_for_each_dev(struct device_driver * drv, void * data,
                               int (*callback)(struct device * dev, void * data));
 
 
+/* driverfs interface for exporting driver attributes */
+
+struct driver_attribute {
+       struct attribute        attr;
+       ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
+       ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+};
+
+#define DRIVER_ATTR(_name,_str,_mode,_show,_store)     \
+struct driver_attribute driver_attr_##_name = {                \
+       .attr = {.name  = _str, .mode   = _mode },      \
+       .show   = _show,                                \
+       .store  = _store,                               \
+};
+
+extern int driver_create_file(struct device_driver *, struct driver_attribute *);
+extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
+
 struct device {
        struct list_head g_list;        /* node in depth-first order list */
        struct list_head node;          /* node in sibling list */