aboutsummaryrefslogtreecommitdiffstats
path: root/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysfs.c')
-rw-r--r--sysfs.c174
1 files changed, 174 insertions, 0 deletions
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);
+}