0001
0002
0003
0004
0005
0006
0007 #include <linux/slab.h>
0008 #include <linux/time.h>
0009 #include <linux/export.h>
0010 #include <linux/errno.h>
0011 #include <sound/core.h>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 int snd_device_new(struct snd_card *card, enum snd_device_type type,
0030 void *device_data, const struct snd_device_ops *ops)
0031 {
0032 struct snd_device *dev;
0033 struct list_head *p;
0034
0035 if (snd_BUG_ON(!card || !device_data || !ops))
0036 return -ENXIO;
0037 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0038 if (!dev)
0039 return -ENOMEM;
0040 INIT_LIST_HEAD(&dev->list);
0041 dev->card = card;
0042 dev->type = type;
0043 dev->state = SNDRV_DEV_BUILD;
0044 dev->device_data = device_data;
0045 dev->ops = ops;
0046
0047
0048 list_for_each_prev(p, &card->devices) {
0049 struct snd_device *pdev = list_entry(p, struct snd_device, list);
0050 if ((unsigned int)pdev->type <= (unsigned int)type)
0051 break;
0052 }
0053
0054 list_add(&dev->list, p);
0055 return 0;
0056 }
0057 EXPORT_SYMBOL(snd_device_new);
0058
0059 static void __snd_device_disconnect(struct snd_device *dev)
0060 {
0061 if (dev->state == SNDRV_DEV_REGISTERED) {
0062 if (dev->ops->dev_disconnect &&
0063 dev->ops->dev_disconnect(dev))
0064 dev_err(dev->card->dev, "device disconnect failure\n");
0065 dev->state = SNDRV_DEV_DISCONNECTED;
0066 }
0067 }
0068
0069 static void __snd_device_free(struct snd_device *dev)
0070 {
0071
0072 list_del(&dev->list);
0073
0074 __snd_device_disconnect(dev);
0075 if (dev->ops->dev_free) {
0076 if (dev->ops->dev_free(dev))
0077 dev_err(dev->card->dev, "device free failure\n");
0078 }
0079 kfree(dev);
0080 }
0081
0082 static struct snd_device *look_for_dev(struct snd_card *card, void *device_data)
0083 {
0084 struct snd_device *dev;
0085
0086 list_for_each_entry(dev, &card->devices, list)
0087 if (dev->device_data == device_data)
0088 return dev;
0089
0090 return NULL;
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 void snd_device_disconnect(struct snd_card *card, void *device_data)
0107 {
0108 struct snd_device *dev;
0109
0110 if (snd_BUG_ON(!card || !device_data))
0111 return;
0112 dev = look_for_dev(card, device_data);
0113 if (dev)
0114 __snd_device_disconnect(dev);
0115 else
0116 dev_dbg(card->dev, "device disconnect %p (from %pS), not found\n",
0117 device_data, __builtin_return_address(0));
0118 }
0119 EXPORT_SYMBOL_GPL(snd_device_disconnect);
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 void snd_device_free(struct snd_card *card, void *device_data)
0131 {
0132 struct snd_device *dev;
0133
0134 if (snd_BUG_ON(!card || !device_data))
0135 return;
0136 dev = look_for_dev(card, device_data);
0137 if (dev)
0138 __snd_device_free(dev);
0139 else
0140 dev_dbg(card->dev, "device free %p (from %pS), not found\n",
0141 device_data, __builtin_return_address(0));
0142 }
0143 EXPORT_SYMBOL(snd_device_free);
0144
0145 static int __snd_device_register(struct snd_device *dev)
0146 {
0147 if (dev->state == SNDRV_DEV_BUILD) {
0148 if (dev->ops->dev_register) {
0149 int err = dev->ops->dev_register(dev);
0150 if (err < 0)
0151 return err;
0152 }
0153 dev->state = SNDRV_DEV_REGISTERED;
0154 }
0155 return 0;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 int snd_device_register(struct snd_card *card, void *device_data)
0172 {
0173 struct snd_device *dev;
0174
0175 if (snd_BUG_ON(!card || !device_data))
0176 return -ENXIO;
0177 dev = look_for_dev(card, device_data);
0178 if (dev)
0179 return __snd_device_register(dev);
0180 snd_BUG();
0181 return -ENXIO;
0182 }
0183 EXPORT_SYMBOL(snd_device_register);
0184
0185
0186
0187
0188
0189 int snd_device_register_all(struct snd_card *card)
0190 {
0191 struct snd_device *dev;
0192 int err;
0193
0194 if (snd_BUG_ON(!card))
0195 return -ENXIO;
0196 list_for_each_entry(dev, &card->devices, list) {
0197 err = __snd_device_register(dev);
0198 if (err < 0)
0199 return err;
0200 }
0201 return 0;
0202 }
0203
0204
0205
0206
0207
0208 void snd_device_disconnect_all(struct snd_card *card)
0209 {
0210 struct snd_device *dev;
0211
0212 if (snd_BUG_ON(!card))
0213 return;
0214 list_for_each_entry_reverse(dev, &card->devices, list)
0215 __snd_device_disconnect(dev);
0216 }
0217
0218
0219
0220
0221
0222 void snd_device_free_all(struct snd_card *card)
0223 {
0224 struct snd_device *dev, *next;
0225
0226 if (snd_BUG_ON(!card))
0227 return;
0228 list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
0229
0230 if (dev->type == SNDRV_DEV_CONTROL ||
0231 dev->type == SNDRV_DEV_LOWLEVEL)
0232 continue;
0233 __snd_device_free(dev);
0234 }
0235
0236
0237 list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
0238 __snd_device_free(dev);
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 int snd_device_get_state(struct snd_card *card, void *device_data)
0254 {
0255 struct snd_device *dev;
0256
0257 dev = look_for_dev(card, device_data);
0258 if (dev)
0259 return dev->state;
0260 return -1;
0261 }
0262 EXPORT_SYMBOL_GPL(snd_device_get_state);