aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--core.c183
-rw-r--r--core.h34
-rw-r--r--sysfs.c174
4 files changed, 218 insertions, 174 deletions
diff --git a/Makefile b/Makefile
index c654996..377e8ec 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_AVIRT) += snd-avirt-core.o
snd-avirt-core-y := core.o
snd-avirt-core-y += pcm.o
snd-avirt-core-y += configfs.o
+snd-avirt-core-y += sysfs.o
ifeq ($(CONFIG_AVIRT_BUILDLOCAL),)
CCFLAGS_AVIRT := "drivers/staging/"
diff --git a/core.c b/core.c
index c1f6393..fd74b08 100644
--- a/core.c
+++ b/core.c
@@ -40,168 +40,6 @@ static struct snd_avirt_core core = {
static LIST_HEAD(audiopath_list);
-struct snd_avirt_audiopath_obj {
- struct kobject kobj;
- struct list_head list;
- struct snd_avirt_audiopath *path;
-};
-
-static struct kset *snd_avirt_audiopath_kset;
-static struct kobject *kobj;
-
-#define to_audiopath_obj(d) \
- container_of(d, struct snd_avirt_audiopath_obj, kobj)
-#define to_audiopath_attr(a) \
- container_of(a, struct snd_avirt_audiopath_attribute, attr)
-
-/**
- * struct snd_avirt_audiopath_attribute - access the attributes of Audio Path
- * @attr: attributes of an Audio Path
- * @show: pointer to the show function
- * @store: pointer to the store function
- */
-struct snd_avirt_audiopath_attribute {
- struct attribute attr;
- ssize_t (*show)(struct snd_avirt_audiopath_obj *d,
- struct snd_avirt_audiopath_attribute *attr, char *buf);
- ssize_t (*store)(struct snd_avirt_audiopath_obj *d,
- struct snd_avirt_audiopath_attribute *attr,
- const char *buf, size_t count);
-};
-
-/**
- * audiopath_attr_show - show function of an Audio Path
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- */
-static ssize_t audiopath_attr_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct snd_avirt_audiopath_attribute *audiopath_attr;
- struct snd_avirt_audiopath_obj *audiopath_obj;
-
- audiopath_attr = to_audiopath_attr(attr);
- audiopath_obj = to_audiopath_obj(kobj);
-
- if (!audiopath_attr->show)
- return -EIO;
-
- return audiopath_attr->show(audiopath_obj, audiopath_attr, buf);
-}
-
-/**
- * audiopath_attr_store - attribute store function of Audio Path object
- * @kobj: pointer to kobject
- * @attr: pointer to attribute struct
- * @buf: buffer
- * @len: length of buffer
- */
-static ssize_t audiopath_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf,
- size_t len)
-{
- struct snd_avirt_audiopath_attribute *audiopath_attr;
- struct snd_avirt_audiopath_obj *audiopath_obj;
-
- audiopath_attr = to_audiopath_attr(attr);
- audiopath_obj = to_audiopath_obj(kobj);
-
- if (!audiopath_attr->store)
- return -EIO;
- return audiopath_attr->store(audiopath_obj, audiopath_attr, buf, len);
-}
-
-static const struct sysfs_ops snd_avirt_audiopath_sysfs_ops = {
- .show = audiopath_attr_show,
- .store = audiopath_attr_store,
-};
-
-/**
- * snd_avirt_audiopath_release - Audio Path release function
- * @kobj: pointer to Audio Paths's kobject
- */
-static void snd_avirt_audiopath_release(struct kobject *kobj)
-{
- struct snd_avirt_audiopath_obj *audiopath_obj = to_audiopath_obj(kobj);
-
- kfree(audiopath_obj);
-}
-
-static ssize_t
- audiopath_name_show(struct snd_avirt_audiopath_obj *audiopath_obj,
- struct snd_avirt_audiopath_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%s\n", audiopath_obj->path->name);
-}
-
-static ssize_t
- audiopath_version_show(struct snd_avirt_audiopath_obj *audiopath_obj,
- struct snd_avirt_audiopath_attribute *attr,
- char *buf)
-{
- struct snd_avirt_audiopath *audiopath = audiopath_obj->path;
-
- return sprintf(buf, "%d.%d.%d\n", audiopath->version[0],
- audiopath->version[1], audiopath->version[2]);
-}
-
-static struct snd_avirt_audiopath_attribute snd_avirt_audiopath_attrs[] = {
- __ATTR_RO(audiopath_name),
- __ATTR_RO(audiopath_version),
-};
-
-static struct attribute *snd_avirt_audiopath_def_attrs[] = {
- &snd_avirt_audiopath_attrs[0].attr,
- &snd_avirt_audiopath_attrs[1].attr,
- NULL,
-};
-
-static struct kobj_type snd_avirt_audiopath_ktype = {
- .sysfs_ops = &snd_avirt_audiopath_sysfs_ops,
- .release = snd_avirt_audiopath_release,
- .default_attrs = snd_avirt_audiopath_def_attrs,
-};
-
-/**
- * create_snd_avirt_audiopath_obj - creates an Audio Path object
- * @uid: Unique ID of the Audio Path
- *
- * This creates an Audio Path object and assigns the kset and registers
- * it with sysfs.
- * @return: Pointer to the Audio Path object or NULL if it failed.
- */
-static struct snd_avirt_audiopath_obj *
- create_snd_avirt_audiopath_obj(const char *uid)
-{
- struct snd_avirt_audiopath_obj *snd_avirt_audiopath;
- int retval;
-
- snd_avirt_audiopath = kzalloc(sizeof(*snd_avirt_audiopath), GFP_KERNEL);
- if (!snd_avirt_audiopath)
- return NULL;
- snd_avirt_audiopath->kobj.kset = snd_avirt_audiopath_kset;
- retval = kobject_init_and_add(&snd_avirt_audiopath->kobj,
- &snd_avirt_audiopath_ktype, kobj, "%s",
- uid);
- if (retval) {
- kobject_put(&snd_avirt_audiopath->kobj);
- return NULL;
- }
- kobject_uevent(&snd_avirt_audiopath->kobj, KOBJ_ADD);
- return snd_avirt_audiopath;
-}
-
-/**
- * destroy_snd_avirt_audiopath_obj - destroys an Audio Path object
- * @name: the Audio Path object
- */
-static void destroy_snd_avirt_audiopath_obj(struct snd_avirt_audiopath_obj *p)
-{
- kobject_put(&p->kobj);
-}
-
/**
* pcm_private_free - callback function to free private data allocated to pcm
* @pcm: the PCM object
@@ -375,7 +213,7 @@ int snd_avirt_audiopath_register(struct snd_avirt_audiopath *audiopath)
return -EINVAL;
}
- audiopath_obj = create_snd_avirt_audiopath_obj(audiopath->uid);
+ audiopath_obj = snd_avirt_audiopath_create_obj(audiopath->uid);
if (!audiopath_obj) {
D_INFOK("Failed to alloc driver object");
return -ENOMEM;
@@ -420,7 +258,7 @@ int snd_avirt_audiopath_deregister(struct snd_avirt_audiopath *audiopath)
}
list_del(&audiopath_obj->list);
- destroy_snd_avirt_audiopath_obj(audiopath_obj);
+ snd_avirt_audiopath_destroy_obj(audiopath_obj);
D_INFOK("Deregistered Audio Path %s", audiopath->uid);
return 0;
@@ -587,18 +425,15 @@ static int __init snd_avirt_core_init(void)
return PTR_ERR(core.class);
}
- core.dev = device_create(core.class, NULL, 0, NULL, "avirtcore");
+ core.dev = device_create(core.class, NULL, 0, NULL, "core");
if (IS_ERR(core.dev)) {
err = PTR_ERR(core.dev);
goto exit_class;
}
- snd_avirt_audiopath_kset =
- kset_create_and_add("audiopaths", NULL, &core.dev->kobj);
- if (!snd_avirt_audiopath_kset) {
- err = -ENOMEM;
+ err = snd_avirt_sysfs_init(&core);
+ if (err < 0)
goto exit_class_container;
- }
err = snd_card_register(core.card);
if (err < 0) {
@@ -608,12 +443,12 @@ static int __init snd_avirt_core_init(void)
err = snd_avirt_configfs_init(&core);
if (err < 0)
- goto exit_kset;
+ goto exit_sysfs;
return 0;
-exit_kset:
- kset_unregister(snd_avirt_audiopath_kset);
+exit_sysfs:
+ snd_avirt_sysfs_exit(&core);
exit_class_container:
device_destroy(core.class, 0);
exit_class:
@@ -631,7 +466,7 @@ exit_platform_device:
static void __exit snd_avirt_core_exit(void)
{
snd_avirt_configfs_exit(&core);
- kset_unregister(snd_avirt_audiopath_kset);
+ snd_avirt_sysfs_exit(&core);
device_destroy(core.class, 0);
class_destroy(core.class);
platform_device_unregister(core.plat_dev);
diff --git a/core.h b/core.h
index 6dc3333..e83631f 100644
--- a/core.h
+++ b/core.h
@@ -27,6 +27,12 @@ struct snd_avirt_core {
bool streams_sealed;
};
+struct snd_avirt_audiopath_obj {
+ struct kobject kobj;
+ struct list_head list;
+ struct snd_avirt_audiopath *path;
+};
+
/**
* snd_avirt_configfs_init - Initialise the configfs system
* @core: The snd_avirt_core pointer
@@ -41,6 +47,34 @@ int __init snd_avirt_configfs_init(struct snd_avirt_core *core);
void __exit snd_avirt_configfs_exit(struct snd_avirt_core *core);
/**
+ * snd_avirt_sysfs_init - Initialise the sysfs system
+ * @core: The snd_avirt_core pointer
+ * @return: 0 on success, negative ERRNO on failure
+ */
+int __init snd_avirt_sysfs_init(struct snd_avirt_core *core);
+
+/**
+ * snd_avirt_sysfs_exit - Clean up and exit the sysfs system
+ * @core: The snd_avirt_core pointer
+ */
+void __exit snd_avirt_sysfs_exit(struct snd_avirt_core *core);
+
+/**
+ * snd_avirt_audiopath_obj - creates an Audio Path object, assigns the kset
+ * and registers it with sysfs.
+ * @uid: Unique ID of the Audio Path
+ * @return: Pointer to the Audio Path object or NULL if it failed.
+ */
+struct snd_avirt_audiopath_obj *snd_avirt_audiopath_create_obj(const char *uid);
+
+/**
+ * snd_avirt_audiopath_destroy_obj - destroys an Audio Path object, deregisters
+ * it with sysfs
+ * @name: the Audio Path object
+ */
+void snd_avirt_audiopath_destroy_obj(struct snd_avirt_audiopath_obj *p);
+
+/**
* snd_avirt_streams_seal - Register the sound card to user space
* @return: 0 on success, negative ERRNO on failure
*/
diff --git a/sysfs.c b/sysfs.c
new file mode 100644
index 0000000..b7d28f5
--- /dev/null
+++ b/sysfs.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AVIRT - ALSA Virtual Soundcard
+ *
+ * Copyright (c) 2010-2019 Fiberdyne Systems Pty Ltd
+ *
+ * configfs.c - AVIRT sysfs support
+ */
+
+#include <linux/slab.h>
+
+#include "core.h"
+
+#define D_LOGNAME "sysfs"
+
+#define D_INFOK(fmt, args...) DINFO(D_LOGNAME, fmt, ##args)
+#define D_PRINTK(fmt, args...) DDEBUG(D_LOGNAME, fmt, ##args)
+#define D_ERRORK(fmt, args...) DERROR(D_LOGNAME, fmt, ##args)
+
+static struct kset *snd_avirt_audiopath_kset;
+static struct kobject *kobj;
+
+#define to_audiopath_obj(d) \
+ container_of(d, struct snd_avirt_audiopath_obj, kobj)
+#define to_audiopath_attr(a) \
+ container_of(a, struct snd_avirt_audiopath_attribute, attr)
+
+/**
+ * struct snd_avirt_audiopath_attribute - access the attributes of Audio Path
+ * @attr: attributes of an Audio Path
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct snd_avirt_audiopath_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct snd_avirt_audiopath_obj *d,
+ struct snd_avirt_audiopath_attribute *attr, char *buf);
+ ssize_t (*store)(struct snd_avirt_audiopath_obj *d,
+ struct snd_avirt_audiopath_attribute *attr,
+ const char *buf, size_t count);
+};
+
+/**
+ * audiopath_attr_show - show function of an Audio Path
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t audiopath_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct snd_avirt_audiopath_attribute *audiopath_attr;
+ struct snd_avirt_audiopath_obj *audiopath_obj;
+
+ audiopath_attr = to_audiopath_attr(attr);
+ audiopath_obj = to_audiopath_obj(kobj);
+
+ if (!audiopath_attr->show)
+ return -EIO;
+
+ return audiopath_attr->show(audiopath_obj, audiopath_attr, buf);
+}
+
+/**
+ * audiopath_attr_store - attribute store function of Audio Path object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t audiopath_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf,
+ size_t len)
+{
+ struct snd_avirt_audiopath_attribute *audiopath_attr;
+ struct snd_avirt_audiopath_obj *audiopath_obj;
+
+ audiopath_attr = to_audiopath_attr(attr);
+ audiopath_obj = to_audiopath_obj(kobj);
+
+ if (!audiopath_attr->store)
+ return -EIO;
+ return audiopath_attr->store(audiopath_obj, audiopath_attr, buf, len);
+}
+
+static const struct sysfs_ops snd_avirt_audiopath_sysfs_ops = {
+ .show = audiopath_attr_show,
+ .store = audiopath_attr_store,
+};
+
+/**
+ * snd_avirt_audiopath_release - Audio Path release function
+ * @kobj: pointer to Audio Paths's kobject
+ */
+static void snd_avirt_audiopath_release(struct kobject *kobj)
+{
+ struct snd_avirt_audiopath_obj *audiopath_obj = to_audiopath_obj(kobj);
+
+ kfree(audiopath_obj);
+}
+
+static ssize_t name_show(struct snd_avirt_audiopath_obj *audiopath_obj,
+ struct snd_avirt_audiopath_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", audiopath_obj->path->name);
+}
+
+static ssize_t version_show(struct snd_avirt_audiopath_obj *audiopath_obj,
+ struct snd_avirt_audiopath_attribute *attr,
+ char *buf)
+{
+ struct snd_avirt_audiopath *audiopath = audiopath_obj->path;
+
+ return sprintf(buf, "%d.%d.%d\n", audiopath->version[0],
+ audiopath->version[1], audiopath->version[2]);
+}
+
+
+static struct snd_avirt_audiopath_attribute snd_avirt_audiopath_attrs[] = {
+ __ATTR_RO(name),
+ __ATTR_RO(version),
+};
+
+static struct attribute *snd_avirt_audiopath_def_attrs[] = {
+ &snd_avirt_audiopath_attrs[0].attr,
+ &snd_avirt_audiopath_attrs[1].attr,
+ NULL,
+};
+
+static struct kobj_type snd_avirt_audiopath_ktype = {
+ .sysfs_ops = &snd_avirt_audiopath_sysfs_ops,
+ .release = snd_avirt_audiopath_release,
+ .default_attrs = snd_avirt_audiopath_def_attrs,
+};
+
+struct snd_avirt_audiopath_obj *snd_avirt_audiopath_create_obj(const char *uid)
+{
+ struct snd_avirt_audiopath_obj *snd_avirt_audiopath;
+ int retval;
+
+ snd_avirt_audiopath = kzalloc(sizeof(*snd_avirt_audiopath), GFP_KERNEL);
+ if (!snd_avirt_audiopath)
+ return NULL;
+ snd_avirt_audiopath->kobj.kset = snd_avirt_audiopath_kset;
+ retval = kobject_init_and_add(&snd_avirt_audiopath->kobj,
+ &snd_avirt_audiopath_ktype, kobj, "%s",
+ uid);
+ if (retval) {
+ kobject_put(&snd_avirt_audiopath->kobj);
+ return NULL;
+ }
+ kobject_uevent(&snd_avirt_audiopath->kobj, KOBJ_ADD);
+ return snd_avirt_audiopath;
+}
+
+void snd_avirt_audiopath_destroy_obj(struct snd_avirt_audiopath_obj *p)
+{
+ kobject_put(&p->kobj);
+}
+
+int __init snd_avirt_sysfs_init(struct snd_avirt_core *core)
+{
+ snd_avirt_audiopath_kset =
+ kset_create_and_add("audiopaths", NULL, &core->dev->kobj);
+ if (!snd_avirt_audiopath_kset)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void __exit snd_avirt_sysfs_exit(struct snd_avirt_core *core)
+{
+ kset_unregister(snd_avirt_audiopath_kset);
+}