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