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 16 static inline struct gb_audio_manager_module *to_gb_audio_module(struct kobject *kobj) 17 { 18 return container_of(kobj, struct gb_audio_manager_module, kobj); 19 } 20 21 struct gb_audio_manager_module_attribute { 22 struct attribute attr; 23 ssize_t (*show)(struct gb_audio_manager_module *module, 24 struct gb_audio_manager_module_attribute *attr, 25 char *buf); 26 ssize_t (*store)(struct gb_audio_manager_module *module, 27 struct gb_audio_manager_module_attribute *attr, 28 const char *buf, size_t count); 29 }; 30 31 static ssize_t gb_audio_module_attr_show(struct kobject *kobj, 32 struct attribute *attr, char *buf) 33 { 34 struct gb_audio_manager_module_attribute *attribute; 35 struct gb_audio_manager_module *module; 36 37 attribute = to_gb_audio_module_attr(attr); 38 module = to_gb_audio_module(kobj); 39 40 if (!attribute->show) 41 return -EIO; 42 43 return attribute->show(module, attribute, buf); 44 } 45 46 static ssize_t gb_audio_module_attr_store(struct kobject *kobj, 47 struct attribute *attr, 48 const char *buf, size_t len) 49 { 50 struct gb_audio_manager_module_attribute *attribute; 51 struct gb_audio_manager_module *module; 52 53 attribute = to_gb_audio_module_attr(attr); 54 module = to_gb_audio_module(kobj); 55 56 if (!attribute->store) 57 return -EIO; 58 59 return attribute->store(module, attribute, buf, len); 60 } 61 62 static const struct sysfs_ops gb_audio_module_sysfs_ops = { 63 .show = gb_audio_module_attr_show, 64 .store = gb_audio_module_attr_store, 65 }; 66 67 static void gb_audio_module_release(struct kobject *kobj) 68 { 69 struct gb_audio_manager_module *module = to_gb_audio_module(kobj); 70 71 pr_info("Destroying audio module #%d\n", module->id); 72 /* TODO -> delete from list */ 73 kfree(module); 74 } 75 76 static ssize_t gb_audio_module_name_show(struct gb_audio_manager_module *module, 77 struct gb_audio_manager_module_attribute *attr, char *buf) 78 { 79 return sprintf(buf, "%s", module->desc.name); 80 } 81 82 static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute = 83 __ATTR(name, 0664, gb_audio_module_name_show, NULL); 84 85 static ssize_t gb_audio_module_vid_show(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 94 static ssize_t gb_audio_module_pid_show(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 100 static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute = 101 __ATTR(pid, 0664, gb_audio_module_pid_show, NULL); 102 103 static ssize_t gb_audio_module_intf_id_show(struct gb_audio_manager_module *module, 104 struct gb_audio_manager_module_attribute *attr, 105 char *buf) 106 { 107 return sprintf(buf, "%d", module->desc.intf_id); 108 } 109 110 static 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 114 static ssize_t gb_audio_module_ip_devices_show(struct gb_audio_manager_module *module, 115 struct gb_audio_manager_module_attribute *attr, 116 char *buf) 117 { 118 return sprintf(buf, "0x%X", module->desc.ip_devices); 119 } 120 121 static 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 125 static ssize_t gb_audio_module_op_devices_show(struct gb_audio_manager_module *module, 126 struct gb_audio_manager_module_attribute *attr, 127 char *buf) 128 { 129 return sprintf(buf, "0x%X", module->desc.op_devices); 130 } 131 132 static 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 136 static 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 ATTRIBUTE_GROUPS(gb_audio_module_default); 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_groups = gb_audio_module_default_groups, 151 }; 152 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 184 int gb_audio_manager_module_create(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 231 void 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