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