/* * a note on stream states used: * we use follwing states in the compressed core * SNDRV_PCM_STATE_OPEN: When stream has been opened. * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by * calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this * state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain. * SNDRV_PCM_STATE_RUNNING: When stream has been started and is * decoding/encoding and rendering/capturing data. * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done * by calling SNDRV_COMPRESS_DRAIN. * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling * SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling * SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively. */ static int snd_compr_open(struct inode *inode, struct file *f) { struct snd_compr *compr; struct snd_compr_file *data; struct snd_compr_runtime *runtime; enum snd_compr_direction dirn; int maj = imajor(inode); int ret; if ((f->f_flags & O_ACCMODE) == O_WRONLY) dirn = SND_COMPRESS_PLAYBACK; else if ((f->f_flags & O_ACCMODE) == O_RDONLY) dirn = SND_COMPRESS_CAPTURE; else return -EINVAL; if (maj == snd_major) compr = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_COMPRESS); else return -EBADFD; if (compr == NULL) { pr_err("no device data!!!\n"); return -ENODEV; } if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { snd_card_unref(compr->card); return -ENOMEM; } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; data->stream.device = compr; runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); data->stream.runtime = runtime; f->private_data = (void *)data; mutex_lock(&compr->lock); ret = compr->ops->open(&data->stream); mutex_unlock(&compr->lock); if (ret) { kfree(runtime); kfree(data); } snd_card_unref(compr->card); return ret; }
static int snd_hwdep_open(struct inode *inode, struct file * file) { int major = imajor(inode); struct snd_hwdep *hw; int err; wait_queue_t wait; if (major == snd_major) { hw = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_HWDEP); #ifdef CONFIG_SND_OSSEMUL } else if (major == SOUND_MAJOR) { hw = snd_lookup_oss_minor_data(iminor(inode), SNDRV_OSS_DEVICE_TYPE_DMFM); #endif } else return -ENXIO; if (hw == NULL) return -ENODEV; if (!try_module_get(hw->card->module)) { snd_card_unref(hw->card); return -EFAULT; } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); mutex_lock(&hw->open_mutex); while (1) { if (hw->exclusive && hw->used > 0) { err = -EBUSY; break; } if (!hw->ops.open) { err = 0; break; } err = hw->ops.open(hw, file); if (err >= 0) break; if (err == -EAGAIN) { if (file->f_flags & O_NONBLOCK) { err = -EBUSY; break; } } else break; set_current_state(TASK_INTERRUPTIBLE); mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); if (hw->card->shutdown) { err = -ENODEV; break; } if (signal_pending(current)) { err = -ERESTARTSYS; break; } } remove_wait_queue(&hw->open_wait, &wait); if (err >= 0) { err = snd_card_file_add(hw->card, file); if (err >= 0) { file->private_data = hw; hw->used++; } else { if (hw->ops.release) hw->ops.release(hw, file); } } mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); snd_card_unref(hw->card); return err; }