linux/drivers/staging/greybus/audio_manager_module.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Greybus operations
   4 *
   5 * Copyright 2015-2016 Google Inc.
   6 */
   7
   8#include <linux/slab.h>
   9
  10#include "audio_manager.h"
  11#include "audio_manager_private.h"
  12
  13#define to_gb_audio_module_attr(x)      \
  14                container_of(x, struct gb_audio_manager_module_attribute, attr)
  15#define to_gb_audio_module(x)           \
  16                container_of(x, struct gb_audio_manager_module, kobj)
  17
  18struct gb_audio_manager_module_attribute {
  19        struct attribute attr;
  20        ssize_t (*show)(struct gb_audio_manager_module *module,
  21                        struct gb_audio_manager_module_attribute *attr,
  22                        char *buf);
  23        ssize_t (*store)(struct gb_audio_manager_module *module,
  24                         struct gb_audio_manager_module_attribute *attr,
  25                         const char *buf, size_t count);
  26};
  27
  28static ssize_t gb_audio_module_attr_show(struct kobject *kobj,
  29                                         struct attribute *attr, char *buf)
  30{
  31        struct gb_audio_manager_module_attribute *attribute;
  32        struct gb_audio_manager_module *module;
  33
  34        attribute = to_gb_audio_module_attr(attr);
  35        module = to_gb_audio_module(kobj);
  36
  37        if (!attribute->show)
  38                return -EIO;
  39
  40        return attribute->show(module, attribute, buf);
  41}
  42
  43static ssize_t gb_audio_module_attr_store(struct kobject *kobj,
  44                                          struct attribute *attr,
  45                                          const char *buf, size_t len)
  46{
  47        struct gb_audio_manager_module_attribute *attribute;
  48        struct gb_audio_manager_module *module;
  49
  50        attribute = to_gb_audio_module_attr(attr);
  51        module = to_gb_audio_module(kobj);
  52
  53        if (!attribute->store)
  54                return -EIO;
  55
  56        return attribute->store(module, attribute, buf, len);
  57}
  58
  59static const struct sysfs_ops gb_audio_module_sysfs_ops = {
  60        .show = gb_audio_module_attr_show,
  61        .store = gb_audio_module_attr_store,
  62};
  63
  64static void gb_audio_module_release(struct kobject *kobj)
  65{
  66        struct gb_audio_manager_module *module = to_gb_audio_module(kobj);
  67
  68        pr_info("Destroying audio module #%d\n", module->id);
  69        /* TODO -> delete from list */
  70        kfree(module);
  71}
  72
  73static ssize_t gb_audio_module_name_show(
  74        struct gb_audio_manager_module *module,
  75        struct gb_audio_manager_module_attribute *attr, char *buf)
  76{
  77        return sprintf(buf, "%s", module->desc.name);
  78}
  79
  80static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute =
  81        __ATTR(name, 0664, gb_audio_module_name_show, NULL);
  82
  83static ssize_t gb_audio_module_vid_show(
  84        struct gb_audio_manager_module *module,
  85        struct gb_audio_manager_module_attribute *attr, char *buf)
  86{
  87        return sprintf(buf, "%d", module->desc.vid);
  88}
  89
  90static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute =
  91        __ATTR(vid, 0664, gb_audio_module_vid_show, NULL);
  92
  93static ssize_t gb_audio_module_pid_show(
  94        struct gb_audio_manager_module *module,
  95        struct gb_audio_manager_module_attribute *attr, char *buf)
  96{
  97        return sprintf(buf, "%d", module->desc.pid);
  98}
  99
 100static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute =
 101        __ATTR(pid, 0664, gb_audio_module_pid_show, NULL);
 102
 103static ssize_t gb_audio_module_intf_id_show(
 104        struct gb_audio_manager_module *module,
 105        struct gb_audio_manager_module_attribute *attr, char *buf)
 106{
 107        return sprintf(buf, "%d", module->desc.intf_id);
 108}
 109
 110static struct gb_audio_manager_module_attribute
 111                                        gb_audio_module_intf_id_attribute =
 112        __ATTR(intf_id, 0664, gb_audio_module_intf_id_show, NULL);
 113
 114static ssize_t gb_audio_module_ip_devices_show(
 115        struct gb_audio_manager_module *module,
 116        struct gb_audio_manager_module_attribute *attr, char *buf)
 117{
 118        return sprintf(buf, "0x%X", module->desc.ip_devices);
 119}
 120
 121static struct gb_audio_manager_module_attribute
 122                                        gb_audio_module_ip_devices_attribute =
 123        __ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL);
 124
 125static ssize_t gb_audio_module_op_devices_show(
 126        struct gb_audio_manager_module *module,
 127        struct gb_audio_manager_module_attribute *attr, char *buf)
 128{
 129        return sprintf(buf, "0x%X", module->desc.op_devices);
 130}
 131
 132static struct gb_audio_manager_module_attribute
 133                                        gb_audio_module_op_devices_attribute =
 134        __ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL);
 135
 136static struct attribute *gb_audio_module_default_attrs[] = {
 137        &gb_audio_module_name_attribute.attr,
 138        &gb_audio_module_vid_attribute.attr,
 139        &gb_audio_module_pid_attribute.attr,
 140        &gb_audio_module_intf_id_attribute.attr,
 141        &gb_audio_module_ip_devices_attribute.attr,
 142        &gb_audio_module_op_devices_attribute.attr,
 143        NULL,   /* need to NULL terminate the list of attributes */
 144};
 145
 146static struct kobj_type gb_audio_module_type = {
 147        .sysfs_ops = &gb_audio_module_sysfs_ops,
 148        .release = gb_audio_module_release,
 149        .default_attrs = gb_audio_module_default_attrs,
 150};
 151
 152static void send_add_uevent(struct gb_audio_manager_module *module)
 153{
 154        char name_string[128];
 155        char vid_string[64];
 156        char pid_string[64];
 157        char intf_id_string[64];
 158        char ip_devices_string[64];
 159        char op_devices_string[64];
 160
 161        char *envp[] = {
 162                name_string,
 163                vid_string,
 164                pid_string,
 165                intf_id_string,
 166                ip_devices_string,
 167                op_devices_string,
 168                NULL
 169        };
 170
 171        snprintf(name_string, 128, "NAME=%s", module->desc.name);
 172        snprintf(vid_string, 64, "VID=%d", module->desc.vid);
 173        snprintf(pid_string, 64, "PID=%d", module->desc.pid);
 174        snprintf(intf_id_string, 64, "INTF_ID=%d", module->desc.intf_id);
 175        snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X",
 176                 module->desc.ip_devices);
 177        snprintf(op_devices_string, 64, "O/P DEVICES=0x%X",
 178                 module->desc.op_devices);
 179
 180        kobject_uevent_env(&module->kobj, KOBJ_ADD, envp);
 181}
 182
 183int gb_audio_manager_module_create(
 184        struct gb_audio_manager_module **module,
 185        struct kset *manager_kset,
 186        int id, struct gb_audio_manager_module_descriptor *desc)
 187{
 188        int err;
 189        struct gb_audio_manager_module *m;
 190
 191        m = kzalloc(sizeof(*m), GFP_ATOMIC);
 192        if (!m)
 193                return -ENOMEM;
 194
 195        /* Initialize the node */
 196        INIT_LIST_HEAD(&m->list);
 197
 198        /* Set the module id */
 199        m->id = id;
 200
 201        /* Copy the provided descriptor */
 202        memcpy(&m->desc, desc, sizeof(*desc));
 203
 204        /* set the kset */
 205        m->kobj.kset = manager_kset;
 206
 207        /*
 208         * Initialize and add the kobject to the kernel.  All the default files
 209         * will be created here.  As we have already specified a kset for this
 210         * kobject, we don't have to set a parent for the kobject, the kobject
 211         * will be placed beneath that kset automatically.
 212         */
 213        err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d",
 214                                   id);
 215        if (err) {
 216                pr_err("failed initializing kobject for audio module #%d\n", id);
 217                kobject_put(&m->kobj);
 218                return err;
 219        }
 220
 221        /*
 222         * Notify the object was created
 223         */
 224        send_add_uevent(m);
 225
 226        *module = m;
 227        pr_info("Created audio module #%d\n", id);
 228        return 0;
 229}
 230
 231void gb_audio_manager_module_dump(struct gb_audio_manager_module *module)
 232{
 233        pr_info("audio module #%d name=%s vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X\n",
 234                module->id,
 235                module->desc.name,
 236                module->desc.vid,
 237                module->desc.pid,
 238                module->desc.intf_id,
 239                module->desc.ip_devices,
 240                module->desc.op_devices);
 241}
 242