Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Initialization routines
4 : : * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
5 : : */
6 : :
7 : : #include <linux/init.h>
8 : : #include <linux/sched.h>
9 : : #include <linux/module.h>
10 : : #include <linux/device.h>
11 : : #include <linux/file.h>
12 : : #include <linux/slab.h>
13 : : #include <linux/time.h>
14 : : #include <linux/ctype.h>
15 : : #include <linux/pm.h>
16 : : #include <linux/completion.h>
17 : :
18 : : #include <sound/core.h>
19 : : #include <sound/control.h>
20 : : #include <sound/info.h>
21 : :
22 : : /* monitor files for graceful shutdown (hotplug) */
23 : : struct snd_monitor_file {
24 : : struct file *file;
25 : : const struct file_operations *disconnected_f_op;
26 : : struct list_head shutdown_list; /* still need to shutdown */
27 : : struct list_head list; /* link of monitor files */
28 : : };
29 : :
30 : : static DEFINE_SPINLOCK(shutdown_lock);
31 : : static LIST_HEAD(shutdown_files);
32 : :
33 : : static const struct file_operations snd_shutdown_f_ops;
34 : :
35 : : /* locked for registering/using */
36 : : static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS);
37 : : static struct snd_card *snd_cards[SNDRV_CARDS];
38 : :
39 : : static DEFINE_MUTEX(snd_card_mutex);
40 : :
41 : : static char *slots[SNDRV_CARDS];
42 : : module_param_array(slots, charp, NULL, 0444);
43 : : MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
44 : :
45 : : /* return non-zero if the given index is reserved for the given
46 : : * module via slots option
47 : : */
48 : 0 : static int module_slot_match(struct module *module, int idx)
49 : : {
50 : 0 : int match = 1;
51 : : #ifdef MODULE
52 : : const char *s1, *s2;
53 : :
54 : : if (!module || !*module->name || !slots[idx])
55 : : return 0;
56 : :
57 : : s1 = module->name;
58 : : s2 = slots[idx];
59 : : if (*s2 == '!') {
60 : : match = 0; /* negative match */
61 : : s2++;
62 : : }
63 : : /* compare module name strings
64 : : * hyphens are handled as equivalent with underscore
65 : : */
66 : : for (;;) {
67 : : char c1 = *s1++;
68 : : char c2 = *s2++;
69 : : if (c1 == '-')
70 : : c1 = '_';
71 : : if (c2 == '-')
72 : : c2 = '_';
73 : : if (c1 != c2)
74 : : return !match;
75 : : if (!c1)
76 : : break;
77 : : }
78 : : #endif /* MODULE */
79 : 0 : return match;
80 : : }
81 : :
82 : : #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
83 : : int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
84 : : EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
85 : : #endif
86 : :
87 : 0 : static int check_empty_slot(struct module *module, int slot)
88 : : {
89 [ # # # # ]: 0 : return !slots[slot] || !*slots[slot];
90 : : }
91 : :
92 : : /* return an empty slot number (>= 0) found in the given bitmask @mask.
93 : : * @mask == -1 == 0xffffffff means: take any free slot up to 32
94 : : * when no slot is available, return the original @mask as is.
95 : : */
96 : 0 : static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int),
97 : : struct module *module)
98 : : {
99 : 0 : int slot;
100 : :
101 [ # # ]: 0 : for (slot = 0; slot < SNDRV_CARDS; slot++) {
102 [ # # ]: 0 : if (slot < 32 && !(mask & (1U << slot)))
103 : 0 : continue;
104 [ # # ]: 0 : if (!test_bit(slot, snd_cards_lock)) {
105 [ # # ]: 0 : if (check(module, slot))
106 : 0 : return slot; /* found */
107 : : }
108 : : }
109 : : return mask; /* unchanged */
110 : : }
111 : :
112 : : /* the default release callback set in snd_device_initialize() below;
113 : : * this is just NOP for now, as almost all jobs are already done in
114 : : * dev_free callback of snd_device chain instead.
115 : : */
116 : 0 : static void default_release(struct device *dev)
117 : : {
118 : 0 : }
119 : :
120 : : /**
121 : : * snd_device_initialize - Initialize struct device for sound devices
122 : : * @dev: device to initialize
123 : : * @card: card to assign, optional
124 : : */
125 : 6 : void snd_device_initialize(struct device *dev, struct snd_card *card)
126 : : {
127 : 6 : device_initialize(dev);
128 [ - + ]: 6 : if (card)
129 : 0 : dev->parent = &card->card_dev;
130 : 6 : dev->class = sound_class;
131 : 6 : dev->release = default_release;
132 : 6 : }
133 : : EXPORT_SYMBOL_GPL(snd_device_initialize);
134 : :
135 : : static int snd_card_do_free(struct snd_card *card);
136 : : static const struct attribute_group card_dev_attr_group;
137 : :
138 : 0 : static void release_card_device(struct device *dev)
139 : : {
140 : 0 : snd_card_do_free(dev_to_snd_card(dev));
141 : 0 : }
142 : :
143 : : /**
144 : : * snd_card_new - create and initialize a soundcard structure
145 : : * @parent: the parent device object
146 : : * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
147 : : * @xid: card identification (ASCII string)
148 : : * @module: top level module for locking
149 : : * @extra_size: allocate this extra size after the main soundcard structure
150 : : * @card_ret: the pointer to store the created card instance
151 : : *
152 : : * Creates and initializes a soundcard structure.
153 : : *
154 : : * The function allocates snd_card instance via kzalloc with the given
155 : : * space for the driver to use freely. The allocated struct is stored
156 : : * in the given card_ret pointer.
157 : : *
158 : : * Return: Zero if successful or a negative error code.
159 : : */
160 : 0 : int snd_card_new(struct device *parent, int idx, const char *xid,
161 : : struct module *module, int extra_size,
162 : : struct snd_card **card_ret)
163 : : {
164 : 0 : struct snd_card *card;
165 : 0 : int err;
166 : :
167 [ # # ]: 0 : if (snd_BUG_ON(!card_ret))
168 : : return -EINVAL;
169 : 0 : *card_ret = NULL;
170 : :
171 : 0 : if (extra_size < 0)
172 : : extra_size = 0;
173 : 0 : card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
174 [ # # ]: 0 : if (!card)
175 : : return -ENOMEM;
176 [ # # ]: 0 : if (extra_size > 0)
177 : 0 : card->private_data = (char *)card + sizeof(struct snd_card);
178 [ # # ]: 0 : if (xid)
179 : 0 : strlcpy(card->id, xid, sizeof(card->id));
180 : 0 : err = 0;
181 : 0 : mutex_lock(&snd_card_mutex);
182 [ # # ]: 0 : if (idx < 0) /* first check the matching module-name slot */
183 : 0 : idx = get_slot_from_bitmask(idx, module_slot_match, module);
184 [ # # ]: 0 : if (idx < 0) /* if not matched, assign an empty slot */
185 : 0 : idx = get_slot_from_bitmask(idx, check_empty_slot, module);
186 [ # # ]: 0 : if (idx < 0)
187 : : err = -ENODEV;
188 [ # # ]: 0 : else if (idx < snd_ecards_limit) {
189 [ # # ]: 0 : if (test_bit(idx, snd_cards_lock))
190 : : err = -EBUSY; /* invalid */
191 [ # # ]: 0 : } else if (idx >= SNDRV_CARDS)
192 : : err = -ENODEV;
193 : : if (err < 0) {
194 : 0 : mutex_unlock(&snd_card_mutex);
195 : 0 : dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
196 : : idx, snd_ecards_limit - 1, err);
197 : 0 : kfree(card);
198 : 0 : return err;
199 : : }
200 : 0 : set_bit(idx, snd_cards_lock); /* lock it */
201 [ # # ]: 0 : if (idx >= snd_ecards_limit)
202 : 0 : snd_ecards_limit = idx + 1; /* increase the limit */
203 : 0 : mutex_unlock(&snd_card_mutex);
204 : 0 : card->dev = parent;
205 : 0 : card->number = idx;
206 : 0 : card->module = module;
207 : 0 : INIT_LIST_HEAD(&card->devices);
208 : 0 : init_rwsem(&card->controls_rwsem);
209 : 0 : rwlock_init(&card->ctl_files_rwlock);
210 : 0 : INIT_LIST_HEAD(&card->controls);
211 : 0 : INIT_LIST_HEAD(&card->ctl_files);
212 : 0 : spin_lock_init(&card->files_lock);
213 : 0 : INIT_LIST_HEAD(&card->files_list);
214 : 0 : mutex_init(&card->memory_mutex);
215 : : #ifdef CONFIG_PM
216 : 0 : init_waitqueue_head(&card->power_sleep);
217 : : #endif
218 : 0 : init_waitqueue_head(&card->remove_sleep);
219 : 0 : card->sync_irq = -1;
220 : :
221 : 0 : device_initialize(&card->card_dev);
222 : 0 : card->card_dev.parent = parent;
223 : 0 : card->card_dev.class = sound_class;
224 : 0 : card->card_dev.release = release_card_device;
225 : 0 : card->card_dev.groups = card->dev_groups;
226 : 0 : card->dev_groups[0] = &card_dev_attr_group;
227 : 0 : err = kobject_set_name(&card->card_dev.kobj, "card%d", idx);
228 [ # # ]: 0 : if (err < 0)
229 : 0 : goto __error;
230 : :
231 [ # # ]: 0 : snprintf(card->irq_descr, sizeof(card->irq_descr), "%s:%s",
232 : 0 : dev_driver_string(card->dev), dev_name(&card->card_dev));
233 : :
234 : : /* the control interface cannot be accessed from the user space until */
235 : : /* snd_cards_bitmask and snd_cards are set with snd_card_register */
236 : 0 : err = snd_ctl_create(card);
237 [ # # ]: 0 : if (err < 0) {
238 : 0 : dev_err(parent, "unable to register control minors\n");
239 : 0 : goto __error;
240 : : }
241 : 0 : err = snd_info_card_create(card);
242 [ # # ]: 0 : if (err < 0) {
243 : 0 : dev_err(parent, "unable to create card info\n");
244 : 0 : goto __error_ctl;
245 : : }
246 : 0 : *card_ret = card;
247 : 0 : return 0;
248 : :
249 : : __error_ctl:
250 : 0 : snd_device_free_all(card);
251 : 0 : __error:
252 : 0 : put_device(&card->card_dev);
253 : 0 : return err;
254 : : }
255 : : EXPORT_SYMBOL(snd_card_new);
256 : :
257 : : /**
258 : : * snd_card_ref - Get the card object from the index
259 : : * @idx: the card index
260 : : *
261 : : * Returns a card object corresponding to the given index or NULL if not found.
262 : : * Release the object via snd_card_unref().
263 : : */
264 : 24 : struct snd_card *snd_card_ref(int idx)
265 : : {
266 : 24 : struct snd_card *card;
267 : :
268 : 24 : mutex_lock(&snd_card_mutex);
269 : 24 : card = snd_cards[idx];
270 [ - + ]: 24 : if (card)
271 : 0 : get_device(&card->card_dev);
272 : 24 : mutex_unlock(&snd_card_mutex);
273 : 24 : return card;
274 : : }
275 : : EXPORT_SYMBOL_GPL(snd_card_ref);
276 : :
277 : : /* return non-zero if a card is already locked */
278 : 0 : int snd_card_locked(int card)
279 : : {
280 : 0 : int locked;
281 : :
282 : 0 : mutex_lock(&snd_card_mutex);
283 : 0 : locked = test_bit(card, snd_cards_lock);
284 : 0 : mutex_unlock(&snd_card_mutex);
285 : 0 : return locked;
286 : : }
287 : :
288 : 0 : static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
289 : : {
290 : 0 : return -ENODEV;
291 : : }
292 : :
293 : 0 : static ssize_t snd_disconnect_read(struct file *file, char __user *buf,
294 : : size_t count, loff_t *offset)
295 : : {
296 : 0 : return -ENODEV;
297 : : }
298 : :
299 : 0 : static ssize_t snd_disconnect_write(struct file *file, const char __user *buf,
300 : : size_t count, loff_t *offset)
301 : : {
302 : 0 : return -ENODEV;
303 : : }
304 : :
305 : 0 : static int snd_disconnect_release(struct inode *inode, struct file *file)
306 : : {
307 : 0 : struct snd_monitor_file *df = NULL, *_df;
308 : :
309 : 0 : spin_lock(&shutdown_lock);
310 [ # # ]: 0 : list_for_each_entry(_df, &shutdown_files, shutdown_list) {
311 [ # # ]: 0 : if (_df->file == file) {
312 : 0 : df = _df;
313 : 0 : list_del_init(&df->shutdown_list);
314 : : break;
315 : : }
316 : : }
317 : 0 : spin_unlock(&shutdown_lock);
318 : :
319 [ # # ]: 0 : if (likely(df)) {
320 [ # # # # ]: 0 : if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync)
321 : 0 : df->disconnected_f_op->fasync(-1, file, 0);
322 : 0 : return df->disconnected_f_op->release(inode, file);
323 : : }
324 : :
325 : 0 : panic("%s(%p, %p) failed!", __func__, inode, file);
326 : : }
327 : :
328 : 0 : static __poll_t snd_disconnect_poll(struct file * file, poll_table * wait)
329 : : {
330 : 0 : return EPOLLERR | EPOLLNVAL;
331 : : }
332 : :
333 : 0 : static long snd_disconnect_ioctl(struct file *file,
334 : : unsigned int cmd, unsigned long arg)
335 : : {
336 : 0 : return -ENODEV;
337 : : }
338 : :
339 : 0 : static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma)
340 : : {
341 : 0 : return -ENODEV;
342 : : }
343 : :
344 : 0 : static int snd_disconnect_fasync(int fd, struct file *file, int on)
345 : : {
346 : 0 : return -ENODEV;
347 : : }
348 : :
349 : : static const struct file_operations snd_shutdown_f_ops =
350 : : {
351 : : .owner = THIS_MODULE,
352 : : .llseek = snd_disconnect_llseek,
353 : : .read = snd_disconnect_read,
354 : : .write = snd_disconnect_write,
355 : : .release = snd_disconnect_release,
356 : : .poll = snd_disconnect_poll,
357 : : .unlocked_ioctl = snd_disconnect_ioctl,
358 : : #ifdef CONFIG_COMPAT
359 : : .compat_ioctl = snd_disconnect_ioctl,
360 : : #endif
361 : : .mmap = snd_disconnect_mmap,
362 : : .fasync = snd_disconnect_fasync
363 : : };
364 : :
365 : : /**
366 : : * snd_card_disconnect - disconnect all APIs from the file-operations (user space)
367 : : * @card: soundcard structure
368 : : *
369 : : * Disconnects all APIs from the file-operations (user space).
370 : : *
371 : : * Return: Zero, otherwise a negative error code.
372 : : *
373 : : * Note: The current implementation replaces all active file->f_op with special
374 : : * dummy file operations (they do nothing except release).
375 : : */
376 : 0 : int snd_card_disconnect(struct snd_card *card)
377 : : {
378 : 0 : struct snd_monitor_file *mfile;
379 : :
380 [ # # ]: 0 : if (!card)
381 : : return -EINVAL;
382 : :
383 : 0 : spin_lock(&card->files_lock);
384 [ # # ]: 0 : if (card->shutdown) {
385 : 0 : spin_unlock(&card->files_lock);
386 : 0 : return 0;
387 : : }
388 : 0 : card->shutdown = 1;
389 : 0 : spin_unlock(&card->files_lock);
390 : :
391 : : /* replace file->f_op with special dummy operations */
392 : 0 : spin_lock(&card->files_lock);
393 [ # # ]: 0 : list_for_each_entry(mfile, &card->files_list, list) {
394 : : /* it's critical part, use endless loop */
395 : : /* we have no room to fail */
396 : 0 : mfile->disconnected_f_op = mfile->file->f_op;
397 : :
398 : 0 : spin_lock(&shutdown_lock);
399 : 0 : list_add(&mfile->shutdown_list, &shutdown_files);
400 : 0 : spin_unlock(&shutdown_lock);
401 : :
402 : 0 : mfile->file->f_op = &snd_shutdown_f_ops;
403 [ # # ]: 0 : fops_get(mfile->file->f_op);
404 : : }
405 : 0 : spin_unlock(&card->files_lock);
406 : :
407 : : /* notify all connected devices about disconnection */
408 : : /* at this point, they cannot respond to any calls except release() */
409 : :
410 : : #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
411 : : if (snd_mixer_oss_notify_callback)
412 : : snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT);
413 : : #endif
414 : :
415 : : /* notify all devices that we are disconnected */
416 : 0 : snd_device_disconnect_all(card);
417 : :
418 : 0 : snd_info_card_disconnect(card);
419 [ # # ]: 0 : if (card->registered) {
420 : 0 : device_del(&card->card_dev);
421 : 0 : card->registered = false;
422 : : }
423 : :
424 : : /* disable fops (user space) operations for ALSA API */
425 : 0 : mutex_lock(&snd_card_mutex);
426 : 0 : snd_cards[card->number] = NULL;
427 : 0 : clear_bit(card->number, snd_cards_lock);
428 : 0 : mutex_unlock(&snd_card_mutex);
429 : :
430 : : #ifdef CONFIG_PM
431 : 0 : wake_up(&card->power_sleep);
432 : : #endif
433 : 0 : return 0;
434 : : }
435 : : EXPORT_SYMBOL(snd_card_disconnect);
436 : :
437 : : /**
438 : : * snd_card_disconnect_sync - disconnect card and wait until files get closed
439 : : * @card: card object to disconnect
440 : : *
441 : : * This calls snd_card_disconnect() for disconnecting all belonging components
442 : : * and waits until all pending files get closed.
443 : : * It assures that all accesses from user-space finished so that the driver
444 : : * can release its resources gracefully.
445 : : */
446 : 0 : void snd_card_disconnect_sync(struct snd_card *card)
447 : : {
448 : 0 : int err;
449 : :
450 : 0 : err = snd_card_disconnect(card);
451 [ # # ]: 0 : if (err < 0) {
452 : 0 : dev_err(card->dev,
453 : : "snd_card_disconnect error (%d), skipping sync\n",
454 : : err);
455 : 0 : return;
456 : : }
457 : :
458 : 0 : spin_lock_irq(&card->files_lock);
459 [ # # # # ]: 0 : wait_event_lock_irq(card->remove_sleep,
460 : : list_empty(&card->files_list),
461 : : card->files_lock);
462 : 0 : spin_unlock_irq(&card->files_lock);
463 : : }
464 : : EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
465 : :
466 : 0 : static int snd_card_do_free(struct snd_card *card)
467 : : {
468 : : #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
469 : : if (snd_mixer_oss_notify_callback)
470 : : snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
471 : : #endif
472 : 0 : snd_device_free_all(card);
473 [ # # ]: 0 : if (card->private_free)
474 : 0 : card->private_free(card);
475 [ # # ]: 0 : if (snd_info_card_free(card) < 0) {
476 : 0 : dev_warn(card->dev, "unable to free card info\n");
477 : : /* Not fatal error */
478 : : }
479 [ # # ]: 0 : if (card->release_completion)
480 : 0 : complete(card->release_completion);
481 : 0 : kfree(card);
482 : 0 : return 0;
483 : : }
484 : :
485 : : /**
486 : : * snd_card_free_when_closed - Disconnect the card, free it later eventually
487 : : * @card: soundcard structure
488 : : *
489 : : * Unlike snd_card_free(), this function doesn't try to release the card
490 : : * resource immediately, but tries to disconnect at first. When the card
491 : : * is still in use, the function returns before freeing the resources.
492 : : * The card resources will be freed when the refcount gets to zero.
493 : : */
494 : 0 : int snd_card_free_when_closed(struct snd_card *card)
495 : : {
496 : 0 : int ret = snd_card_disconnect(card);
497 [ # # # # ]: 0 : if (ret)
498 : : return ret;
499 : 0 : put_device(&card->card_dev);
500 : 0 : return 0;
501 : : }
502 : : EXPORT_SYMBOL(snd_card_free_when_closed);
503 : :
504 : : /**
505 : : * snd_card_free - frees given soundcard structure
506 : : * @card: soundcard structure
507 : : *
508 : : * This function releases the soundcard structure and the all assigned
509 : : * devices automatically. That is, you don't have to release the devices
510 : : * by yourself.
511 : : *
512 : : * This function waits until the all resources are properly released.
513 : : *
514 : : * Return: Zero. Frees all associated devices and frees the control
515 : : * interface associated to given soundcard.
516 : : */
517 : 0 : int snd_card_free(struct snd_card *card)
518 : : {
519 : 0 : struct completion released;
520 : 0 : int ret;
521 : :
522 : 0 : init_completion(&released);
523 : 0 : card->release_completion = &released;
524 : 0 : ret = snd_card_free_when_closed(card);
525 : 0 : if (ret)
526 : : return ret;
527 : : /* wait, until all devices are ready for the free operation */
528 : 0 : wait_for_completion(&released);
529 : 0 : return 0;
530 : : }
531 : : EXPORT_SYMBOL(snd_card_free);
532 : :
533 : : /* retrieve the last word of shortname or longname */
534 : 0 : static const char *retrieve_id_from_card_name(const char *name)
535 : : {
536 : 0 : const char *spos = name;
537 : :
538 [ # # ]: 0 : while (*name) {
539 [ # # # # ]: 0 : if (isspace(*name) && isalnum(name[1]))
540 : 0 : spos = name + 1;
541 : 0 : name++;
542 : : }
543 : 0 : return spos;
544 : : }
545 : :
546 : : /* return true if the given id string doesn't conflict any other card ids */
547 : 0 : static bool card_id_ok(struct snd_card *card, const char *id)
548 : : {
549 : 0 : int i;
550 [ # # ]: 0 : if (!snd_info_check_reserved_words(id))
551 : : return false;
552 [ # # ]: 0 : for (i = 0; i < snd_ecards_limit; i++) {
553 [ # # # # ]: 0 : if (snd_cards[i] && snd_cards[i] != card &&
554 [ # # ]: 0 : !strcmp(snd_cards[i]->id, id))
555 : : return false;
556 : : }
557 : : return true;
558 : : }
559 : :
560 : : /* copy to card->id only with valid letters from nid */
561 : 0 : static void copy_valid_id_string(struct snd_card *card, const char *src,
562 : : const char *nid)
563 : : {
564 : 0 : char *id = card->id;
565 : :
566 [ # # # # ]: 0 : while (*nid && !isalnum(*nid))
567 : 0 : nid++;
568 [ # # ]: 0 : if (isdigit(*nid))
569 [ # # ]: 0 : *id++ = isalpha(*src) ? *src : 'D';
570 [ # # # # ]: 0 : while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
571 [ # # ]: 0 : if (isalnum(*nid))
572 : 0 : *id++ = *nid;
573 : 0 : nid++;
574 : : }
575 : 0 : *id = 0;
576 : 0 : }
577 : :
578 : : /* Set card->id from the given string
579 : : * If the string conflicts with other ids, add a suffix to make it unique.
580 : : */
581 : 0 : static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
582 : : const char *nid)
583 : : {
584 : 0 : int len, loops;
585 : 0 : bool is_default = false;
586 : 0 : char *id;
587 : :
588 : 0 : copy_valid_id_string(card, src, nid);
589 : 0 : id = card->id;
590 : :
591 : 0 : again:
592 : : /* use "Default" for obviously invalid strings
593 : : * ("card" conflicts with proc directories)
594 : : */
595 [ # # # # ]: 0 : if (!*id || !strncmp(id, "card", 4)) {
596 : 0 : strcpy(id, "Default");
597 : 0 : is_default = true;
598 : : }
599 : :
600 : 0 : len = strlen(id);
601 [ # # ]: 0 : for (loops = 0; loops < SNDRV_CARDS; loops++) {
602 : 0 : char *spos;
603 : 0 : char sfxstr[5]; /* "_012" */
604 : 0 : int sfxlen;
605 : :
606 [ # # ]: 0 : if (card_id_ok(card, id))
607 : 0 : return; /* OK */
608 : :
609 : : /* Add _XYZ suffix */
610 : 0 : sprintf(sfxstr, "_%X", loops + 1);
611 : 0 : sfxlen = strlen(sfxstr);
612 [ # # ]: 0 : if (len + sfxlen >= sizeof(card->id))
613 : 0 : spos = id + sizeof(card->id) - sfxlen - 1;
614 : : else
615 : 0 : spos = id + len;
616 : 0 : strcpy(spos, sfxstr);
617 : : }
618 : : /* fallback to the default id */
619 [ # # ]: 0 : if (!is_default) {
620 : 0 : *id = 0;
621 : 0 : goto again;
622 : : }
623 : : /* last resort... */
624 : 0 : dev_err(card->dev, "unable to set card id (%s)\n", id);
625 [ # # ]: 0 : if (card->proc_root->name)
626 : 0 : strlcpy(card->id, card->proc_root->name, sizeof(card->id));
627 : : }
628 : :
629 : : /**
630 : : * snd_card_set_id - set card identification name
631 : : * @card: soundcard structure
632 : : * @nid: new identification string
633 : : *
634 : : * This function sets the card identification and checks for name
635 : : * collisions.
636 : : */
637 : 0 : void snd_card_set_id(struct snd_card *card, const char *nid)
638 : : {
639 : : /* check if user specified own card->id */
640 [ # # ]: 0 : if (card->id[0] != '\0')
641 : : return;
642 : 0 : mutex_lock(&snd_card_mutex);
643 : 0 : snd_card_set_id_no_lock(card, nid, nid);
644 : 0 : mutex_unlock(&snd_card_mutex);
645 : : }
646 : : EXPORT_SYMBOL(snd_card_set_id);
647 : :
648 : : static ssize_t
649 : 0 : card_id_show_attr(struct device *dev,
650 : : struct device_attribute *attr, char *buf)
651 : : {
652 : 0 : struct snd_card *card = container_of(dev, struct snd_card, card_dev);
653 : 0 : return scnprintf(buf, PAGE_SIZE, "%s\n", card->id);
654 : : }
655 : :
656 : : static ssize_t
657 : 0 : card_id_store_attr(struct device *dev, struct device_attribute *attr,
658 : : const char *buf, size_t count)
659 : : {
660 : 0 : struct snd_card *card = container_of(dev, struct snd_card, card_dev);
661 : 0 : char buf1[sizeof(card->id)];
662 : 0 : size_t copy = count > sizeof(card->id) - 1 ?
663 : : sizeof(card->id) - 1 : count;
664 : 0 : size_t idx;
665 : 0 : int c;
666 : :
667 [ # # ]: 0 : for (idx = 0; idx < copy; idx++) {
668 : 0 : c = buf[idx];
669 [ # # # # ]: 0 : if (!isalnum(c) && c != '_' && c != '-')
670 : : return -EINVAL;
671 : : }
672 : 0 : memcpy(buf1, buf, copy);
673 : 0 : buf1[copy] = '\0';
674 : 0 : mutex_lock(&snd_card_mutex);
675 [ # # ]: 0 : if (!card_id_ok(NULL, buf1)) {
676 : 0 : mutex_unlock(&snd_card_mutex);
677 : 0 : return -EEXIST;
678 : : }
679 : 0 : strcpy(card->id, buf1);
680 : 0 : snd_info_card_id_change(card);
681 : 0 : mutex_unlock(&snd_card_mutex);
682 : :
683 : 0 : return count;
684 : : }
685 : :
686 : : static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
687 : :
688 : : static ssize_t
689 : 0 : card_number_show_attr(struct device *dev,
690 : : struct device_attribute *attr, char *buf)
691 : : {
692 : 0 : struct snd_card *card = container_of(dev, struct snd_card, card_dev);
693 : 0 : return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
694 : : }
695 : :
696 : : static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
697 : :
698 : : static struct attribute *card_dev_attrs[] = {
699 : : &dev_attr_id.attr,
700 : : &dev_attr_number.attr,
701 : : NULL
702 : : };
703 : :
704 : : static const struct attribute_group card_dev_attr_group = {
705 : : .attrs = card_dev_attrs,
706 : : };
707 : :
708 : : /**
709 : : * snd_card_add_dev_attr - Append a new sysfs attribute group to card
710 : : * @card: card instance
711 : : * @group: attribute group to append
712 : : */
713 : 0 : int snd_card_add_dev_attr(struct snd_card *card,
714 : : const struct attribute_group *group)
715 : : {
716 : 0 : int i;
717 : :
718 : : /* loop for (arraysize-1) here to keep NULL at the last entry */
719 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(card->dev_groups) - 1; i++) {
720 [ # # ]: 0 : if (!card->dev_groups[i]) {
721 : 0 : card->dev_groups[i] = group;
722 : 0 : return 0;
723 : : }
724 : : }
725 : :
726 : 0 : dev_err(card->dev, "Too many groups assigned\n");
727 : 0 : return -ENOSPC;
728 : : }
729 : : EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
730 : :
731 : : /**
732 : : * snd_card_register - register the soundcard
733 : : * @card: soundcard structure
734 : : *
735 : : * This function registers all the devices assigned to the soundcard.
736 : : * Until calling this, the ALSA control interface is blocked from the
737 : : * external accesses. Thus, you should call this function at the end
738 : : * of the initialization of the card.
739 : : *
740 : : * Return: Zero otherwise a negative error code if the registration failed.
741 : : */
742 : 0 : int snd_card_register(struct snd_card *card)
743 : : {
744 : 0 : int err;
745 : :
746 [ # # ]: 0 : if (snd_BUG_ON(!card))
747 : : return -EINVAL;
748 : :
749 [ # # ]: 0 : if (!card->registered) {
750 : 0 : err = device_add(&card->card_dev);
751 [ # # ]: 0 : if (err < 0)
752 : : return err;
753 : 0 : card->registered = true;
754 : : }
755 : :
756 [ # # ]: 0 : if ((err = snd_device_register_all(card)) < 0)
757 : : return err;
758 : 0 : mutex_lock(&snd_card_mutex);
759 [ # # ]: 0 : if (snd_cards[card->number]) {
760 : : /* already registered */
761 : 0 : mutex_unlock(&snd_card_mutex);
762 : 0 : return snd_info_card_register(card); /* register pending info */
763 : : }
764 [ # # ]: 0 : if (*card->id) {
765 : : /* make a unique id name from the given string */
766 : 0 : char tmpid[sizeof(card->id)];
767 : 0 : memcpy(tmpid, card->id, sizeof(card->id));
768 : 0 : snd_card_set_id_no_lock(card, tmpid, tmpid);
769 : : } else {
770 : : /* create an id from either shortname or longname */
771 : 0 : const char *src;
772 [ # # ]: 0 : src = *card->shortname ? card->shortname : card->longname;
773 : 0 : snd_card_set_id_no_lock(card, src,
774 : : retrieve_id_from_card_name(src));
775 : : }
776 : 0 : snd_cards[card->number] = card;
777 : 0 : mutex_unlock(&snd_card_mutex);
778 : 0 : err = snd_info_card_register(card);
779 : 0 : if (err < 0)
780 : : return err;
781 : :
782 : : #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
783 : : if (snd_mixer_oss_notify_callback)
784 : : snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
785 : : #endif
786 : : return 0;
787 : : }
788 : : EXPORT_SYMBOL(snd_card_register);
789 : :
790 : : #ifdef CONFIG_SND_PROC_FS
791 : 0 : static void snd_card_info_read(struct snd_info_entry *entry,
792 : : struct snd_info_buffer *buffer)
793 : : {
794 : 0 : int idx, count;
795 : 0 : struct snd_card *card;
796 : :
797 [ # # ]: 0 : for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
798 : 0 : mutex_lock(&snd_card_mutex);
799 [ # # ]: 0 : if ((card = snd_cards[idx]) != NULL) {
800 : 0 : count++;
801 : 0 : snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
802 : : idx,
803 : : card->id,
804 : : card->driver,
805 : : card->shortname);
806 : 0 : snd_iprintf(buffer, " %s\n",
807 : : card->longname);
808 : : }
809 : 0 : mutex_unlock(&snd_card_mutex);
810 : : }
811 [ # # ]: 0 : if (!count)
812 : 0 : snd_iprintf(buffer, "--- no soundcards ---\n");
813 : 0 : }
814 : :
815 : : #ifdef CONFIG_SND_OSSEMUL
816 : : void snd_card_info_read_oss(struct snd_info_buffer *buffer)
817 : : {
818 : : int idx, count;
819 : : struct snd_card *card;
820 : :
821 : : for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
822 : : mutex_lock(&snd_card_mutex);
823 : : if ((card = snd_cards[idx]) != NULL) {
824 : : count++;
825 : : snd_iprintf(buffer, "%s\n", card->longname);
826 : : }
827 : : mutex_unlock(&snd_card_mutex);
828 : : }
829 : : if (!count) {
830 : : snd_iprintf(buffer, "--- no soundcards ---\n");
831 : : }
832 : : }
833 : :
834 : : #endif
835 : :
836 : : #ifdef MODULE
837 : : static void snd_card_module_info_read(struct snd_info_entry *entry,
838 : : struct snd_info_buffer *buffer)
839 : : {
840 : : int idx;
841 : : struct snd_card *card;
842 : :
843 : : for (idx = 0; idx < SNDRV_CARDS; idx++) {
844 : : mutex_lock(&snd_card_mutex);
845 : : if ((card = snd_cards[idx]) != NULL)
846 : : snd_iprintf(buffer, "%2i %s\n",
847 : : idx, card->module->name);
848 : : mutex_unlock(&snd_card_mutex);
849 : : }
850 : : }
851 : : #endif
852 : :
853 : 3 : int __init snd_card_info_init(void)
854 : : {
855 : 3 : struct snd_info_entry *entry;
856 : :
857 : 3 : entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
858 [ + - ]: 3 : if (! entry)
859 : : return -ENOMEM;
860 : 3 : entry->c.text.read = snd_card_info_read;
861 [ - + ]: 3 : if (snd_info_register(entry) < 0)
862 : 0 : return -ENOMEM; /* freed in error path */
863 : :
864 : : #ifdef MODULE
865 : : entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
866 : : if (!entry)
867 : : return -ENOMEM;
868 : : entry->c.text.read = snd_card_module_info_read;
869 : : if (snd_info_register(entry) < 0)
870 : : return -ENOMEM; /* freed in error path */
871 : : #endif
872 : :
873 : : return 0;
874 : : }
875 : : #endif /* CONFIG_SND_PROC_FS */
876 : :
877 : : /**
878 : : * snd_component_add - add a component string
879 : : * @card: soundcard structure
880 : : * @component: the component id string
881 : : *
882 : : * This function adds the component id string to the supported list.
883 : : * The component can be referred from the alsa-lib.
884 : : *
885 : : * Return: Zero otherwise a negative error code.
886 : : */
887 : :
888 : 0 : int snd_component_add(struct snd_card *card, const char *component)
889 : : {
890 : 0 : char *ptr;
891 : 0 : int len = strlen(component);
892 : :
893 : 0 : ptr = strstr(card->components, component);
894 [ # # ]: 0 : if (ptr != NULL) {
895 [ # # ]: 0 : if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */
896 : : return 1;
897 : : }
898 [ # # ]: 0 : if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) {
899 : : snd_BUG();
900 : : return -ENOMEM;
901 : : }
902 [ # # ]: 0 : if (card->components[0] != '\0')
903 : 0 : strcat(card->components, " ");
904 : 0 : strcat(card->components, component);
905 : 0 : return 0;
906 : : }
907 : : EXPORT_SYMBOL(snd_component_add);
908 : :
909 : : /**
910 : : * snd_card_file_add - add the file to the file list of the card
911 : : * @card: soundcard structure
912 : : * @file: file pointer
913 : : *
914 : : * This function adds the file to the file linked-list of the card.
915 : : * This linked-list is used to keep tracking the connection state,
916 : : * and to avoid the release of busy resources by hotplug.
917 : : *
918 : : * Return: zero or a negative error code.
919 : : */
920 : 0 : int snd_card_file_add(struct snd_card *card, struct file *file)
921 : : {
922 : 0 : struct snd_monitor_file *mfile;
923 : :
924 : 0 : mfile = kmalloc(sizeof(*mfile), GFP_KERNEL);
925 [ # # ]: 0 : if (mfile == NULL)
926 : : return -ENOMEM;
927 : 0 : mfile->file = file;
928 : 0 : mfile->disconnected_f_op = NULL;
929 : 0 : INIT_LIST_HEAD(&mfile->shutdown_list);
930 : 0 : spin_lock(&card->files_lock);
931 [ # # ]: 0 : if (card->shutdown) {
932 : 0 : spin_unlock(&card->files_lock);
933 : 0 : kfree(mfile);
934 : 0 : return -ENODEV;
935 : : }
936 : 0 : list_add(&mfile->list, &card->files_list);
937 : 0 : get_device(&card->card_dev);
938 : 0 : spin_unlock(&card->files_lock);
939 : 0 : return 0;
940 : : }
941 : : EXPORT_SYMBOL(snd_card_file_add);
942 : :
943 : : /**
944 : : * snd_card_file_remove - remove the file from the file list
945 : : * @card: soundcard structure
946 : : * @file: file pointer
947 : : *
948 : : * This function removes the file formerly added to the card via
949 : : * snd_card_file_add() function.
950 : : * If all files are removed and snd_card_free_when_closed() was
951 : : * called beforehand, it processes the pending release of
952 : : * resources.
953 : : *
954 : : * Return: Zero or a negative error code.
955 : : */
956 : 0 : int snd_card_file_remove(struct snd_card *card, struct file *file)
957 : : {
958 : 0 : struct snd_monitor_file *mfile, *found = NULL;
959 : :
960 : 0 : spin_lock(&card->files_lock);
961 [ # # ]: 0 : list_for_each_entry(mfile, &card->files_list, list) {
962 [ # # ]: 0 : if (mfile->file == file) {
963 : 0 : list_del(&mfile->list);
964 : 0 : spin_lock(&shutdown_lock);
965 : 0 : list_del(&mfile->shutdown_list);
966 : 0 : spin_unlock(&shutdown_lock);
967 [ # # ]: 0 : if (mfile->disconnected_f_op)
968 : 0 : fops_put(mfile->disconnected_f_op);
969 : : found = mfile;
970 : : break;
971 : : }
972 : : }
973 [ # # ]: 0 : if (list_empty(&card->files_list))
974 : 0 : wake_up_all(&card->remove_sleep);
975 : 0 : spin_unlock(&card->files_lock);
976 [ # # ]: 0 : if (!found) {
977 : 0 : dev_err(card->dev, "card file remove problem (%p)\n", file);
978 : 0 : return -ENOENT;
979 : : }
980 : 0 : kfree(found);
981 : 0 : put_device(&card->card_dev);
982 : 0 : return 0;
983 : : }
984 : : EXPORT_SYMBOL(snd_card_file_remove);
985 : :
986 : : #ifdef CONFIG_PM
987 : : /**
988 : : * snd_power_wait - wait until the power-state is changed.
989 : : * @card: soundcard structure
990 : : * @power_state: expected power state
991 : : *
992 : : * Waits until the power-state is changed.
993 : : *
994 : : * Return: Zero if successful, or a negative error code.
995 : : */
996 : 0 : int snd_power_wait(struct snd_card *card, unsigned int power_state)
997 : : {
998 : 0 : wait_queue_entry_t wait;
999 : 0 : int result = 0;
1000 : :
1001 : : /* fastpath */
1002 [ # # ]: 0 : if (snd_power_get_state(card) == power_state)
1003 : : return 0;
1004 : 0 : init_waitqueue_entry(&wait, current);
1005 : 0 : add_wait_queue(&card->power_sleep, &wait);
1006 : 0 : while (1) {
1007 [ # # ]: 0 : if (card->shutdown) {
1008 : : result = -ENODEV;
1009 : : break;
1010 : : }
1011 [ # # ]: 0 : if (snd_power_get_state(card) == power_state)
1012 : : break;
1013 : 0 : set_current_state(TASK_UNINTERRUPTIBLE);
1014 : 0 : schedule_timeout(30 * HZ);
1015 : : }
1016 : 0 : remove_wait_queue(&card->power_sleep, &wait);
1017 : 0 : return result;
1018 : : }
1019 : : EXPORT_SYMBOL(snd_power_wait);
1020 : : #endif /* CONFIG_PM */
|