~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/core/init.c

Version: ~ [ linux-5.2-rc4 ] ~ [ linux-5.1.9 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.50 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.125 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.181 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.181 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.68 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp