diff options
Diffstat (limited to 'drivers/dahdi/dahdi-sysfs.c')
-rw-r--r-- | drivers/dahdi/dahdi-sysfs.c | 150 |
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); |