• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
gb_audio_module_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)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 
gb_audio_module_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)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 
gb_audio_module_release(struct kobject * kobj)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 
gb_audio_module_name_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)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 
gb_audio_module_vid_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)84 static ssize_t gb_audio_module_vid_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.vid);
89 }
90 
91 static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute =
92 	__ATTR(vid, 0664, gb_audio_module_vid_show, NULL);
93 
gb_audio_module_pid_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)94 static ssize_t gb_audio_module_pid_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.pid);
99 }
100 
101 static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute =
102 	__ATTR(pid, 0664, gb_audio_module_pid_show, NULL);
103 
gb_audio_module_intf_id_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)104 static ssize_t gb_audio_module_intf_id_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.intf_id);
109 }
110 
111 static struct gb_audio_manager_module_attribute
112 					gb_audio_module_intf_id_attribute =
113 	__ATTR(intf_id, 0664, gb_audio_module_intf_id_show, NULL);
114 
gb_audio_module_ip_devices_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)115 static ssize_t gb_audio_module_ip_devices_show(
116 	struct gb_audio_manager_module *module,
117 	struct gb_audio_manager_module_attribute *attr, char *buf)
118 {
119 	return sprintf(buf, "0x%X", module->desc.ip_devices);
120 }
121 
122 static struct gb_audio_manager_module_attribute
123 					gb_audio_module_ip_devices_attribute =
124 	__ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL);
125 
gb_audio_module_op_devices_show(struct gb_audio_manager_module * module,struct gb_audio_manager_module_attribute * attr,char * buf)126 static ssize_t gb_audio_module_op_devices_show(
127 	struct gb_audio_manager_module *module,
128 	struct gb_audio_manager_module_attribute *attr, char *buf)
129 {
130 	return sprintf(buf, "0x%X", module->desc.op_devices);
131 }
132 
133 static struct gb_audio_manager_module_attribute
134 					gb_audio_module_op_devices_attribute =
135 	__ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL);
136 
137 static struct attribute *gb_audio_module_default_attrs[] = {
138 	&gb_audio_module_name_attribute.attr,
139 	&gb_audio_module_vid_attribute.attr,
140 	&gb_audio_module_pid_attribute.attr,
141 	&gb_audio_module_intf_id_attribute.attr,
142 	&gb_audio_module_ip_devices_attribute.attr,
143 	&gb_audio_module_op_devices_attribute.attr,
144 	NULL,   /* need to NULL terminate the list of attributes */
145 };
146 
147 static struct kobj_type gb_audio_module_type = {
148 	.sysfs_ops = &gb_audio_module_sysfs_ops,
149 	.release = gb_audio_module_release,
150 	.default_attrs = gb_audio_module_default_attrs,
151 };
152 
send_add_uevent(struct gb_audio_manager_module * module)153 static void send_add_uevent(struct gb_audio_manager_module *module)
154 {
155 	char name_string[128];
156 	char vid_string[64];
157 	char pid_string[64];
158 	char intf_id_string[64];
159 	char ip_devices_string[64];
160 	char op_devices_string[64];
161 
162 	char *envp[] = {
163 		name_string,
164 		vid_string,
165 		pid_string,
166 		intf_id_string,
167 		ip_devices_string,
168 		op_devices_string,
169 		NULL
170 	};
171 
172 	snprintf(name_string, 128, "NAME=%s", module->desc.name);
173 	snprintf(vid_string, 64, "VID=%d", module->desc.vid);
174 	snprintf(pid_string, 64, "PID=%d", module->desc.pid);
175 	snprintf(intf_id_string, 64, "INTF_ID=%d", module->desc.intf_id);
176 	snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X",
177 		 module->desc.ip_devices);
178 	snprintf(op_devices_string, 64, "O/P DEVICES=0x%X",
179 		 module->desc.op_devices);
180 
181 	kobject_uevent_env(&module->kobj, KOBJ_ADD, envp);
182 }
183 
gb_audio_manager_module_create(struct gb_audio_manager_module ** module,struct kset * manager_kset,int id,struct gb_audio_manager_module_descriptor * desc)184 int gb_audio_manager_module_create(
185 	struct gb_audio_manager_module **module,
186 	struct kset *manager_kset,
187 	int id, struct gb_audio_manager_module_descriptor *desc)
188 {
189 	int err;
190 	struct gb_audio_manager_module *m;
191 
192 	m = kzalloc(sizeof(*m), GFP_ATOMIC);
193 	if (!m)
194 		return -ENOMEM;
195 
196 	/* Initialize the node */
197 	INIT_LIST_HEAD(&m->list);
198 
199 	/* Set the module id */
200 	m->id = id;
201 
202 	/* Copy the provided descriptor */
203 	memcpy(&m->desc, desc, sizeof(*desc));
204 
205 	/* set the kset */
206 	m->kobj.kset = manager_kset;
207 
208 	/*
209 	 * Initialize and add the kobject to the kernel.  All the default files
210 	 * will be created here.  As we have already specified a kset for this
211 	 * kobject, we don't have to set a parent for the kobject, the kobject
212 	 * will be placed beneath that kset automatically.
213 	 */
214 	err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d",
215 				   id);
216 	if (err) {
217 		pr_err("failed initializing kobject for audio module #%d\n",
218 		       id);
219 		kobject_put(&m->kobj);
220 		return err;
221 	}
222 
223 	/*
224 	 * Notify the object was created
225 	 */
226 	send_add_uevent(m);
227 
228 	*module = m;
229 	pr_info("Created audio module #%d\n", id);
230 	return 0;
231 }
232 
gb_audio_manager_module_dump(struct gb_audio_manager_module * module)233 void gb_audio_manager_module_dump(struct gb_audio_manager_module *module)
234 {
235 	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",
236 		module->id,
237 		module->desc.name,
238 		module->desc.vid,
239 		module->desc.pid,
240 		module->desc.intf_id,
241 		module->desc.ip_devices,
242 		module->desc.op_devices);
243 }
244