0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/device.h>
0025 #include <linux/init.h>
0026 #include <linux/module.h>
0027 #include <sound/core.h>
0028 #include <sound/info.h>
0029 #include <sound/seq_device.h>
0030 #include <sound/seq_kernel.h>
0031 #include <sound/initval.h>
0032 #include <linux/kmod.h>
0033 #include <linux/slab.h>
0034 #include <linux/mutex.h>
0035
0036 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
0037 MODULE_DESCRIPTION("ALSA sequencer device management");
0038 MODULE_LICENSE("GPL");
0039
0040
0041
0042
0043 static int snd_seq_bus_match(struct device *dev, struct device_driver *drv)
0044 {
0045 struct snd_seq_device *sdev = to_seq_dev(dev);
0046 struct snd_seq_driver *sdrv = to_seq_drv(drv);
0047
0048 return strcmp(sdrv->id, sdev->id) == 0 &&
0049 sdrv->argsize == sdev->argsize;
0050 }
0051
0052 static struct bus_type snd_seq_bus_type = {
0053 .name = "snd_seq",
0054 .match = snd_seq_bus_match,
0055 };
0056
0057
0058
0059
0060 #ifdef CONFIG_SND_PROC_FS
0061 static struct snd_info_entry *info_entry;
0062
0063 static int print_dev_info(struct device *dev, void *data)
0064 {
0065 struct snd_seq_device *sdev = to_seq_dev(dev);
0066 struct snd_info_buffer *buffer = data;
0067
0068 snd_iprintf(buffer, "snd-%s,%s,%d\n", sdev->id,
0069 dev->driver ? "loaded" : "empty",
0070 dev->driver ? 1 : 0);
0071 return 0;
0072 }
0073
0074 static void snd_seq_device_info(struct snd_info_entry *entry,
0075 struct snd_info_buffer *buffer)
0076 {
0077 bus_for_each_dev(&snd_seq_bus_type, NULL, buffer, print_dev_info);
0078 }
0079 #endif
0080
0081
0082
0083
0084
0085 #ifdef CONFIG_MODULES
0086
0087 static atomic_t snd_seq_in_init = ATOMIC_INIT(1);
0088
0089 static int request_seq_drv(struct device *dev, void *data)
0090 {
0091 struct snd_seq_device *sdev = to_seq_dev(dev);
0092
0093 if (!dev->driver)
0094 request_module("snd-%s", sdev->id);
0095 return 0;
0096 }
0097
0098 static void autoload_drivers(struct work_struct *work)
0099 {
0100
0101 if (atomic_inc_return(&snd_seq_in_init) == 1)
0102 bus_for_each_dev(&snd_seq_bus_type, NULL, NULL,
0103 request_seq_drv);
0104 atomic_dec(&snd_seq_in_init);
0105 }
0106
0107 static DECLARE_WORK(autoload_work, autoload_drivers);
0108
0109 static void queue_autoload_drivers(void)
0110 {
0111 schedule_work(&autoload_work);
0112 }
0113
0114 void snd_seq_autoload_init(void)
0115 {
0116 atomic_dec(&snd_seq_in_init);
0117 #ifdef CONFIG_SND_SEQUENCER_MODULE
0118
0119 queue_autoload_drivers();
0120 #endif
0121 }
0122 EXPORT_SYMBOL(snd_seq_autoload_init);
0123
0124 void snd_seq_autoload_exit(void)
0125 {
0126 atomic_inc(&snd_seq_in_init);
0127 }
0128 EXPORT_SYMBOL(snd_seq_autoload_exit);
0129
0130 void snd_seq_device_load_drivers(void)
0131 {
0132 queue_autoload_drivers();
0133 flush_work(&autoload_work);
0134 }
0135 EXPORT_SYMBOL(snd_seq_device_load_drivers);
0136
0137 static inline void cancel_autoload_drivers(void)
0138 {
0139 cancel_work_sync(&autoload_work);
0140 }
0141 #else
0142 static inline void queue_autoload_drivers(void)
0143 {
0144 }
0145
0146 static inline void cancel_autoload_drivers(void)
0147 {
0148 }
0149 #endif
0150
0151
0152
0153
0154 static int snd_seq_device_dev_free(struct snd_device *device)
0155 {
0156 struct snd_seq_device *dev = device->device_data;
0157
0158 cancel_autoload_drivers();
0159 if (dev->private_free)
0160 dev->private_free(dev);
0161 put_device(&dev->dev);
0162 return 0;
0163 }
0164
0165 static int snd_seq_device_dev_register(struct snd_device *device)
0166 {
0167 struct snd_seq_device *dev = device->device_data;
0168 int err;
0169
0170 err = device_add(&dev->dev);
0171 if (err < 0)
0172 return err;
0173 if (!dev->dev.driver)
0174 queue_autoload_drivers();
0175 return 0;
0176 }
0177
0178 static int snd_seq_device_dev_disconnect(struct snd_device *device)
0179 {
0180 struct snd_seq_device *dev = device->device_data;
0181
0182 device_del(&dev->dev);
0183 return 0;
0184 }
0185
0186 static void snd_seq_dev_release(struct device *dev)
0187 {
0188 kfree(to_seq_dev(dev));
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198 int snd_seq_device_new(struct snd_card *card, int device, const char *id,
0199 int argsize, struct snd_seq_device **result)
0200 {
0201 struct snd_seq_device *dev;
0202 int err;
0203 static const struct snd_device_ops dops = {
0204 .dev_free = snd_seq_device_dev_free,
0205 .dev_register = snd_seq_device_dev_register,
0206 .dev_disconnect = snd_seq_device_dev_disconnect,
0207 };
0208
0209 if (result)
0210 *result = NULL;
0211
0212 if (snd_BUG_ON(!id))
0213 return -EINVAL;
0214
0215 dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL);
0216 if (!dev)
0217 return -ENOMEM;
0218
0219
0220 dev->card = card;
0221 dev->device = device;
0222 dev->id = id;
0223 dev->argsize = argsize;
0224
0225 device_initialize(&dev->dev);
0226 dev->dev.parent = &card->card_dev;
0227 dev->dev.bus = &snd_seq_bus_type;
0228 dev->dev.release = snd_seq_dev_release;
0229 dev_set_name(&dev->dev, "%s-%d-%d", dev->id, card->number, device);
0230
0231
0232 err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops);
0233 if (err < 0) {
0234 put_device(&dev->dev);
0235 return err;
0236 }
0237
0238 if (result)
0239 *result = dev;
0240
0241 return 0;
0242 }
0243 EXPORT_SYMBOL(snd_seq_device_new);
0244
0245
0246
0247
0248 int __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod)
0249 {
0250 if (WARN_ON(!drv->driver.name || !drv->id))
0251 return -EINVAL;
0252 drv->driver.bus = &snd_seq_bus_type;
0253 drv->driver.owner = mod;
0254 return driver_register(&drv->driver);
0255 }
0256 EXPORT_SYMBOL_GPL(__snd_seq_driver_register);
0257
0258 void snd_seq_driver_unregister(struct snd_seq_driver *drv)
0259 {
0260 driver_unregister(&drv->driver);
0261 }
0262 EXPORT_SYMBOL_GPL(snd_seq_driver_unregister);
0263
0264
0265
0266
0267
0268 static int __init seq_dev_proc_init(void)
0269 {
0270 #ifdef CONFIG_SND_PROC_FS
0271 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
0272 snd_seq_root);
0273 if (info_entry == NULL)
0274 return -ENOMEM;
0275 info_entry->content = SNDRV_INFO_CONTENT_TEXT;
0276 info_entry->c.text.read = snd_seq_device_info;
0277 if (snd_info_register(info_entry) < 0) {
0278 snd_info_free_entry(info_entry);
0279 return -ENOMEM;
0280 }
0281 #endif
0282 return 0;
0283 }
0284
0285 static int __init alsa_seq_device_init(void)
0286 {
0287 int err;
0288
0289 err = bus_register(&snd_seq_bus_type);
0290 if (err < 0)
0291 return err;
0292 err = seq_dev_proc_init();
0293 if (err < 0)
0294 bus_unregister(&snd_seq_bus_type);
0295 return err;
0296 }
0297
0298 static void __exit alsa_seq_device_exit(void)
0299 {
0300 #ifdef CONFIG_MODULES
0301 cancel_work_sync(&autoload_work);
0302 #endif
0303 #ifdef CONFIG_SND_PROC_FS
0304 snd_info_free_entry(info_entry);
0305 #endif
0306 bus_unregister(&snd_seq_bus_type);
0307 }
0308
0309 subsys_initcall(alsa_seq_device_init)
0310 module_exit(alsa_seq_device_exit)