1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ALSA sequencer device management 4 * Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de> 5 * 6 *---------------------------------------------------------------- 7 * 8 * This device handler separates the card driver module from sequencer 9 * stuff (sequencer core, synth drivers, etc), so that user can avoid 10 * to spend unnecessary resources e.g. if he needs only listening to 11 * MP3s. 12 * 13 * The card (or lowlevel) driver creates a sequencer device entry 14 * via snd_seq_device_new(). This is an entry pointer to communicate 15 * with the sequencer device "driver", which is involved with the 16 * actual part to communicate with the sequencer core. 17 * Each sequencer device entry has an id string and the corresponding 18 * driver with the same id is loaded when required. For example, 19 * lowlevel codes to access emu8000 chip on sbawe card are included in 20 * emu8000-synth module. To activate this module, the hardware 21 * resources like i/o port are passed via snd_seq_device argument. 22 */ 23 24 #include <linux/device.h> 25 #include <linux/init.h> 26 #include <linux/module.h> 27 #include <sound/core.h> 28 #include <sound/info.h> 29 #include <sound/seq_device.h> 30 #include <sound/seq_kernel.h> 31 #include <sound/initval.h> 32 #include <linux/kmod.h> 33 #include <linux/slab.h> 34 #include <linux/mutex.h> 35 36 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 37 MODULE_DESCRIPTION("ALSA sequencer device management"); 38 MODULE_LICENSE("GPL"); 39 40 /* 41 * bus definition 42 */ 43 static int snd_seq_bus_match(struct device *dev, const struct device_driver *drv) 44 { 45 struct snd_seq_device *sdev = to_seq_dev(dev); 46 const struct snd_seq_driver *sdrv = to_seq_drv(drv); 47 48 return strcmp(sdrv->id, sdev->id) == 0 && 49 sdrv->argsize == sdev->argsize; 50 } 51 52 static int snd_seq_bus_probe(struct device *dev) 53 { 54 struct snd_seq_device *sdev = to_seq_dev(dev); 55 const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver); 56 57 if (sdrv->probe) 58 return sdrv->probe(sdev); 59 else 60 return 0; 61 } 62 63 static void snd_seq_bus_remove(struct device *dev) 64 { 65 struct snd_seq_device *sdev = to_seq_dev(dev); 66 const struct snd_seq_driver *sdrv = to_seq_drv(dev->driver); 67 68 if (sdrv->remove) 69 sdrv->remove(sdev); 70 } 71 72 static const struct bus_type snd_seq_bus_type = { 73 .name = "snd_seq", 74 .match = snd_seq_bus_match, 75 .probe = snd_seq_bus_probe, 76 .remove = snd_seq_bus_remove, 77 }; 78 79 /* 80 * proc interface -- just for compatibility 81 */ 82 #ifdef CONFIG_SND_PROC_FS 83 static struct snd_info_entry *info_entry; 84 85 static int print_dev_info(struct device *dev, void *data) 86 { 87 struct snd_seq_device *sdev = to_seq_dev(dev); 88 struct snd_info_buffer *buffer = data; 89 90 snd_iprintf(buffer, "snd-%s,%s,%d\n", sdev->id, 91 dev->driver ? "loaded" : "empty", 92 dev->driver ? 1 : 0); 93 return 0; 94 } 95 96 static void snd_seq_device_info(struct snd_info_entry *entry, 97 struct snd_info_buffer *buffer) 98 { 99 bus_for_each_dev(&snd_seq_bus_type, NULL, buffer, print_dev_info); 100 } 101 #endif 102 103 /* 104 * load all registered drivers (called from seq_clientmgr.c) 105 */ 106 107 #ifdef CONFIG_MODULES 108 /* flag to block auto-loading */ 109 static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ 110 111 static int request_seq_drv(struct device *dev, void *data) 112 { 113 struct snd_seq_device *sdev = to_seq_dev(dev); 114 115 if (!dev->driver) 116 request_module("snd-%s", sdev->id); 117 return 0; 118 } 119 120 static void autoload_drivers(struct work_struct *work) 121 { 122 /* avoid reentrance */ 123 if (atomic_inc_return(&snd_seq_in_init) == 1) 124 bus_for_each_dev(&snd_seq_bus_type, NULL, NULL, 125 request_seq_drv); 126 atomic_dec(&snd_seq_in_init); 127 } 128 129 static DECLARE_WORK(autoload_work, autoload_drivers); 130 131 static void queue_autoload_drivers(void) 132 { 133 schedule_work(&autoload_work); 134 } 135 136 void snd_seq_autoload_init(void) 137 { 138 atomic_dec(&snd_seq_in_init); 139 #ifdef CONFIG_SND_SEQUENCER_MODULE 140 /* initial autoload only when snd-seq is a module */ 141 queue_autoload_drivers(); 142 #endif 143 } 144 EXPORT_SYMBOL(snd_seq_autoload_init); 145 146 void snd_seq_autoload_exit(void) 147 { 148 atomic_inc(&snd_seq_in_init); 149 } 150 EXPORT_SYMBOL(snd_seq_autoload_exit); 151 152 void snd_seq_device_load_drivers(void) 153 { 154 queue_autoload_drivers(); 155 flush_work(&autoload_work); 156 } 157 EXPORT_SYMBOL(snd_seq_device_load_drivers); 158 159 static inline void cancel_autoload_drivers(void) 160 { 161 cancel_work_sync(&autoload_work); 162 } 163 #else 164 static inline void queue_autoload_drivers(void) 165 { 166 } 167 168 static inline void cancel_autoload_drivers(void) 169 { 170 } 171 #endif 172 173 /* 174 * device management 175 */ 176 static int snd_seq_device_dev_free(struct snd_device *device) 177 { 178 struct snd_seq_device *dev = device->device_data; 179 180 cancel_autoload_drivers(); 181 if (dev->private_free) 182 dev->private_free(dev); 183 put_device(&dev->dev); 184 return 0; 185 } 186 187 static int snd_seq_device_dev_register(struct snd_device *device) 188 { 189 struct snd_seq_device *dev = device->device_data; 190 int err; 191 192 err = device_add(&dev->dev); 193 if (err < 0) 194 return err; 195 if (!dev->dev.driver) 196 queue_autoload_drivers(); 197 return 0; 198 } 199 200 static int snd_seq_device_dev_disconnect(struct snd_device *device) 201 { 202 struct snd_seq_device *dev = device->device_data; 203 204 device_del(&dev->dev); 205 return 0; 206 } 207 208 static void snd_seq_dev_release(struct device *dev) 209 { 210 kfree(to_seq_dev(dev)); 211 } 212 213 /* 214 * register a sequencer device 215 * card = card info 216 * device = device number (if any) 217 * id = id of driver 218 * result = return pointer (NULL allowed if unnecessary) 219 */ 220 int snd_seq_device_new(struct snd_card *card, int device, const char *id, 221 int argsize, struct snd_seq_device **result) 222 { 223 struct snd_seq_device *dev; 224 int err; 225 static const struct snd_device_ops dops = { 226 .dev_free = snd_seq_device_dev_free, 227 .dev_register = snd_seq_device_dev_register, 228 .dev_disconnect = snd_seq_device_dev_disconnect, 229 }; 230 231 if (result) 232 *result = NULL; 233 234 if (snd_BUG_ON(!id)) 235 return -EINVAL; 236 237 dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL); 238 if (!dev) 239 return -ENOMEM; 240 241 /* set up device info */ 242 dev->card = card; 243 dev->device = device; 244 dev->id = id; 245 dev->argsize = argsize; 246 247 device_initialize(&dev->dev); 248 dev->dev.parent = &card->card_dev; 249 dev->dev.bus = &snd_seq_bus_type; 250 dev->dev.release = snd_seq_dev_release; 251 dev_set_name(&dev->dev, "%s-%d-%d", dev->id, card->number, device); 252 253 /* add this device to the list */ 254 err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops); 255 if (err < 0) { 256 put_device(&dev->dev); 257 return err; 258 } 259 260 if (result) 261 *result = dev; 262 263 return 0; 264 } 265 EXPORT_SYMBOL(snd_seq_device_new); 266 267 static int snd_seq_driver_legacy_probe(struct snd_seq_device *sdev) 268 { 269 struct device *dev = &sdev->dev; 270 struct device_driver *driver = dev->driver; 271 272 return driver->probe(dev); 273 } 274 275 static void snd_seq_driver_legacy_remove(struct snd_seq_device *sdev) 276 { 277 struct device *dev = &sdev->dev; 278 struct device_driver *driver = dev->driver; 279 int ret; 280 281 ret = driver->remove(dev); 282 if (unlikely(ret)) 283 dev_warn(dev, "Ignoring return value of remove callback (%pe)\n", ERR_PTR(ret)); 284 } 285 286 /* 287 * driver registration 288 */ 289 int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod) 290 { 291 if (WARN_ON(!drv->driver.name || !drv->id)) 292 return -EINVAL; 293 drv->driver.bus = &snd_seq_bus_type; 294 drv->driver.owner = mod; 295 296 if (!drv->probe && drv->driver.probe) 297 drv->probe = snd_seq_driver_legacy_probe; 298 if (!drv->remove && drv->driver.remove) 299 drv->remove = snd_seq_driver_legacy_remove; 300 301 return driver_register(&drv->driver); 302 } 303 EXPORT_SYMBOL_GPL(__snd_seq_driver_register); 304 305 void snd_seq_driver_unregister(struct snd_seq_driver *drv) 306 { 307 driver_unregister(&drv->driver); 308 } 309 EXPORT_SYMBOL_GPL(snd_seq_driver_unregister); 310 311 /* 312 * module part 313 */ 314 315 static int __init seq_dev_proc_init(void) 316 { 317 #ifdef CONFIG_SND_PROC_FS 318 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", 319 snd_seq_root); 320 if (info_entry == NULL) 321 return -ENOMEM; 322 info_entry->content = SNDRV_INFO_CONTENT_TEXT; 323 info_entry->c.text.read = snd_seq_device_info; 324 if (snd_info_register(info_entry) < 0) { 325 snd_info_free_entry(info_entry); 326 return -ENOMEM; 327 } 328 #endif 329 return 0; 330 } 331 332 static int __init alsa_seq_device_init(void) 333 { 334 int err; 335 336 err = bus_register(&snd_seq_bus_type); 337 if (err < 0) 338 return err; 339 err = seq_dev_proc_init(); 340 if (err < 0) 341 bus_unregister(&snd_seq_bus_type); 342 return err; 343 } 344 345 static void __exit alsa_seq_device_exit(void) 346 { 347 #ifdef CONFIG_MODULES 348 cancel_work_sync(&autoload_work); 349 #endif 350 #ifdef CONFIG_SND_PROC_FS 351 snd_info_free_entry(info_entry); 352 #endif 353 bus_unregister(&snd_seq_bus_type); 354 } 355 356 subsys_initcall(alsa_seq_device_init) 357 module_exit(alsa_seq_device_exit) 358