summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi-sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dahdi/dahdi-sysfs.c')
-rw-r--r--drivers/dahdi/dahdi-sysfs.c150
1 files changed, 142 insertions, 8 deletions
diff --git a/drivers/dahdi/dahdi-sysfs.c b/drivers/dahdi/dahdi-sysfs.c
index 2ed4c06..02677dd 100644
--- a/drivers/dahdi/dahdi-sysfs.c
+++ b/drivers/dahdi/dahdi-sysfs.c
@@ -113,7 +113,7 @@ static int span_match(struct device *dev, struct device_driver *driver)
return 1;
}
-static inline struct dahdi_span *dev_to_span(const struct device *const dev)
+static inline struct dahdi_span *dev_to_span(struct device *const dev)
{
return dev_get_drvdata(dev);
}
@@ -236,7 +236,6 @@ static struct device_attribute span_dev_attrs[] = {
__ATTR_NULL,
};
-
static struct driver_attribute dahdi_attrs[] = {
__ATTR_NULL,
};
@@ -313,7 +312,6 @@ static void span_release(struct device *dev)
dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev));
}
-
int dahdi_register_chardev(struct dahdi_chardev *dev)
{
static const char *DAHDI_STRING = "dahdi!";
@@ -348,10 +346,8 @@ void span_sysfs_remove(struct dahdi_span *span)
span_dbg(DEVICES, span, "\n");
span_device = span->span_device;
- if (!span_device) {
- WARN_ON(!span_device);
+ if (!span_device)
return;
- }
for (x = 0; x < span->channels; x++) {
struct dahdi_chan *chan = span->chans[x];
@@ -376,7 +372,10 @@ int span_sysfs_create(struct dahdi_span *span)
int res = 0;
int x;
- BUG_ON(span->span_device);
+ if (span->span_device) {
+ WARN_ON(1);
+ return -EEXIST;
+ }
span->span_device = kzalloc(sizeof(*span->span_device), GFP_KERNEL);
if (!span->span_device)
@@ -386,7 +385,7 @@ int span_sysfs_create(struct dahdi_span *span)
span_dbg(DEVICES, span, "\n");
span_device->bus = &spans_bus_type;
- span_device->parent = span->parent->dev.parent;
+ span_device->parent = &span->parent->dev;
dev_set_name(span_device, "span-%03d", span->spanno);
dev_set_drvdata(span_device, span);
span_device->release = span_release;
@@ -441,8 +440,94 @@ static struct {
unsigned int pseudo:1;
unsigned int sysfs_driver_registered:1;
unsigned int sysfs_spans_bus_type:1;
+ unsigned int dahdi_device_bus_registered:1;
} dummy_dev;
+static inline struct dahdi_device *to_ddev(struct device *dev)
+{
+ return container_of(dev, struct dahdi_device, dev);
+}
+
+static ssize_t
+dahdi_device_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dahdi_device *ddev = to_ddev(dev);
+ return sprintf(buf, "%s\n", ddev->manufacturer);
+}
+
+static ssize_t
+dahdi_device_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dahdi_device *ddev = to_ddev(dev);
+ return sprintf(buf, "%s\n", ddev->devicetype);
+}
+
+static ssize_t
+dahdi_device_span_count_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dahdi_device *ddev = to_ddev(dev);
+ unsigned int count = 0;
+ struct list_head *pos;
+
+ list_for_each(pos, &ddev->spans)
+ ++count;
+
+ return sprintf(buf, "%d\n", count);
+}
+
+static ssize_t
+dahdi_device_auto_register(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dahdi_device *ddev = to_ddev(dev);
+ dahdi_register_device_spans(ddev);
+ return count;
+}
+
+static ssize_t
+dahdi_device_register_span(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ struct dahdi_span *span;
+ unsigned int span_offset;
+ unsigned int desired_spanno;
+ unsigned int desired_basechanno;
+ struct dahdi_device *const ddev = to_ddev(dev);
+
+ ret = sscanf(buf, "%u:%u:%u", &span_offset, &desired_spanno,
+ &desired_basechanno);
+ if (ret != 3)
+ return -EINVAL;
+
+ list_for_each_entry(span, &ddev->spans, device_node) {
+ if (span_offset == span->offset) {
+ ret = dahdi_register_span(span, desired_spanno,
+ desired_basechanno, 1);
+ return (ret) ? ret : count;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static struct device_attribute dahdi_device_attrs[] = {
+ __ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
+ __ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
+ __ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
+ __ATTR(auto_register, S_IWUSR, NULL, dahdi_device_auto_register),
+ __ATTR(register_span, S_IWUSR, NULL, dahdi_device_register_span),
+ __ATTR_NULL,
+};
+
+static struct bus_type dahdi_device_bus = {
+ .name = "dahdi_devices",
+ .dev_attrs = dahdi_device_attrs,
+};
+
void dahdi_sysfs_exit(void)
{
dahdi_dbg(DEVICES, "SYSFS\n");
@@ -482,6 +567,49 @@ void dahdi_sysfs_exit(void)
dummy_dev.sysfs_spans_bus_type = 0;
}
unregister_chrdev(DAHDI_MAJOR, "dahdi");
+
+ if (dummy_dev.dahdi_device_bus_registered) {
+ bus_unregister(&dahdi_device_bus);
+ dummy_dev.dahdi_device_bus_registered = 0;
+ }
+}
+
+static void dahdi_device_release(struct device *dev)
+{
+ struct dahdi_device *ddev = container_of(dev, struct dahdi_device, dev);
+ kfree(ddev);
+}
+
+/**
+ * dahdi_sysfs_add_device - Add the dahdi_device into the sysfs hierarchy.
+ * @ddev: The device to add.
+ * @parent: The physical device that is implementing this device.
+ *
+ * By adding the dahdi_device to the sysfs hierarchy user space can control
+ * how spans are numbered.
+ *
+ */
+int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent)
+{
+ int ret;
+ struct device *const dev = &ddev->dev;
+
+ dev->parent = parent;
+ dev->bus = &dahdi_device_bus;
+ dev->release = dahdi_device_release;
+ dev_set_name(dev, "dahdi:%s:%s", parent->bus->name, dev_name(parent));
+ ret = device_add(dev);
+ return ret;
+}
+
+void dahdi_sysfs_init_device(struct dahdi_device *ddev)
+{
+ device_initialize(&ddev->dev);
+}
+
+void dahdi_sysfs_unregister_device(struct dahdi_device *ddev)
+{
+ device_del(&ddev->dev);
}
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
@@ -489,6 +617,12 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
int res = 0;
void *dev;
+ res = bus_register(&dahdi_device_bus);
+ if (res)
+ return res;
+
+ dummy_dev.dahdi_device_bus_registered = 1;
+
res = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops);
if (res) {
module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);