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 /* 268 * driver registration 269 */ 270 int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod) 271 { 272 if (WARN_ON(!drv->driver.name || !drv->id || drv->driver.probe || drv->driver.remove)) 273 return -EINVAL; 274 275 drv->driver.bus = &snd_seq_bus_type; 276 drv->driver.owner = mod; 277 278 return driver_register(&drv->driver); 279 } 280 EXPORT_SYMBOL_GPL(__snd_seq_driver_register); 281 282 void snd_seq_driver_unregister(struct snd_seq_driver *drv) 283 { 284 driver_unregister(&drv->driver); 285 } 286 EXPORT_SYMBOL_GPL(snd_seq_driver_unregister); 287 288 /* 289 * module part 290 */ 291 292 static int __init seq_dev_proc_init(void) 293 { 294 #ifdef CONFIG_SND_PROC_FS 295 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", 296 snd_seq_root); 297 if (info_entry == NULL) 298 return -ENOMEM; 299 info_entry->content = SNDRV_INFO_CONTENT_TEXT; 300 info_entry->c.text.read = snd_seq_device_info; 301 if (snd_info_register(info_entry) < 0) { 302 snd_info_free_entry(info_entry); 303 return -ENOMEM; 304 } 305 #endif 306 return 0; 307 } 308 309 static int __init alsa_seq_device_init(void) 310 { 311 int err; 312 313 err = bus_register(&snd_seq_bus_type); 314 if (err < 0) 315 return err; 316 err = seq_dev_proc_init(); 317 if (err < 0) 318 bus_unregister(&snd_seq_bus_type); 319 return err; 320 } 321 322 static void __exit alsa_seq_device_exit(void) 323 { 324 #ifdef CONFIG_MODULES 325 cancel_work_sync(&autoload_work); 326 #endif 327 #ifdef CONFIG_SND_PROC_FS 328 snd_info_free_entry(info_entry); 329 #endif 330 bus_unregister(&snd_seq_bus_type); 331 } 332 333 subsys_initcall(alsa_seq_device_init) 334 module_exit(alsa_seq_device_exit) 335