Commit 9eba2d84 authored by Patrick Mochel's avatar Patrick Mochel

driverfs: Add ability to create and remove files for bus drivers

These behave identically to device attribute files, but with different types. 

We get struct bus_attribute, and a macro, BUS_ATTR for declaring attributes. It takes the same parameters
as DEVICE_ATTR, though the callbacks for bus attributes take a struct bus_type as the first parameter.
parent 2b553d80
#include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/stat.h> #include <linux/stat.h>
#include "fs.h" #include "fs.h"
static struct driver_dir_entry bus_dir = { static struct driver_dir_entry bus_dir;
name: "bus",
mode: (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO), #define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
#define to_bus(dir) container_of(dir,struct bus_type,dir)
/* driverfs ops for device attribute files */
static int
bus_attr_open(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
get_bus(bus);
return 0;
}
static int
bus_attr_close(struct driver_dir_entry * dir)
{
struct bus_type * bus = to_bus(dir);
put_bus(bus);
return 0;
}
static ssize_t
bus_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->show)
ret = bus_attr->show(bus,buf,count,off);
return ret;
}
static ssize_t
bus_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
const char * buf, size_t count, loff_t off)
{
struct bus_attribute * bus_attr = to_bus_attr(attr);
struct bus_type * bus = to_bus(dir);
ssize_t ret = 0;
if (bus_attr->store)
ret = bus_attr->store(bus,buf,count,off);
return ret;
}
static struct driverfs_ops bus_attr_ops = {
open: bus_attr_open,
close: bus_attr_close,
show: bus_attr_show,
store: bus_attr_store,
}; };
int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
{
int error;
if (get_bus(bus)) {
error = driverfs_create_file(&attr->attr,&bus->dir);
put_bus(bus);
} else
error = -EINVAL;
return error;
}
void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
{
if (get_bus(bus)) {
driverfs_remove_file(&bus->dir,attr->attr.name);
put_bus(bus);
}
}
int bus_make_dir(struct bus_type * bus) int bus_make_dir(struct bus_type * bus)
{ {
int error; int error;
bus->dir.name = bus->name; bus->dir.name = bus->name;
bus->dir.ops = &bus_attr_ops;
error = device_create_dir(&bus->dir,&bus_dir); error = device_create_dir(&bus->dir,&bus_dir);
if (!error) { if (!error) {
...@@ -32,6 +106,11 @@ void bus_remove_dir(struct bus_type * bus) ...@@ -32,6 +106,11 @@ void bus_remove_dir(struct bus_type * bus)
driverfs_remove_dir(&bus->dir); driverfs_remove_dir(&bus->dir);
} }
static struct driver_dir_entry bus_dir = {
name: "bus",
mode: (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
};
static int __init bus_init(void) static int __init bus_init(void)
{ {
/* make 'bus' driverfs directory */ /* make 'bus' driverfs directory */
...@@ -40,3 +119,5 @@ static int __init bus_init(void) ...@@ -40,3 +119,5 @@ static int __init bus_init(void)
core_initcall(bus_init); core_initcall(bus_init);
EXPORT_SYMBOL(bus_create_file);
EXPORT_SYMBOL(bus_remove_file);
...@@ -85,6 +85,24 @@ extern int bus_for_each_drv(struct bus_type * bus, void * data, ...@@ -85,6 +85,24 @@ extern int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data)); int (*callback)(struct device_driver * drv, void * data));
/* driverfs interface for exporting bus attributes */
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
};
#define BUS_ATTR(_name,_str,_mode,_show,_store) \
struct bus_attribute bus_attr_##_name = { \
.attr = {.name = _str, .mode = _mode }, \
.show = _show, \
.store = _store, \
};
extern int bus_create_file(struct bus_type *, struct bus_attribute *);
extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
struct device_driver { struct device_driver {
char * name; char * name;
struct bus_type * bus; struct bus_type * bus;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment