mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-13 09:54:04 +00:00
[ALSA] Clean up PCM codes (take 2)
- Clean up initialization and destruction of substream instance Now snd_pcm_open_substream() alone does most initialization jobs. Add pcm_release callback for cleaning up at snd_pcm_release_substream() - Tidy up PCM oss code Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
bf1bbb5a49
commit
3bf75f9b90
6 changed files with 114 additions and 219 deletions
|
@ -369,6 +369,7 @@ struct snd_pcm_substream {
|
||||||
/* -- assigned files -- */
|
/* -- assigned files -- */
|
||||||
struct snd_pcm_file *file;
|
struct snd_pcm_file *file;
|
||||||
struct file *ffile;
|
struct file *ffile;
|
||||||
|
void (*pcm_release)(struct snd_pcm_substream *);
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
||||||
/* -- OSS things -- */
|
/* -- OSS things -- */
|
||||||
struct snd_pcm_oss_substream oss;
|
struct snd_pcm_oss_substream oss;
|
||||||
|
@ -381,13 +382,10 @@ struct snd_pcm_substream {
|
||||||
struct snd_info_entry *proc_prealloc_entry;
|
struct snd_info_entry *proc_prealloc_entry;
|
||||||
/* misc flags */
|
/* misc flags */
|
||||||
unsigned int no_mmap_ctrl: 1;
|
unsigned int no_mmap_ctrl: 1;
|
||||||
|
unsigned int hw_opened: 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
|
||||||
#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
|
|
||||||
#else
|
|
||||||
#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
|
#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct snd_pcm_str {
|
struct snd_pcm_str {
|
||||||
|
@ -468,8 +466,12 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream);
|
||||||
int snd_pcm_suspend_all(struct snd_pcm *pcm);
|
int snd_pcm_suspend_all(struct snd_pcm *pcm);
|
||||||
#endif
|
#endif
|
||||||
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
|
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
|
||||||
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
|
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
|
||||||
|
struct snd_pcm_substream **rsubstream);
|
||||||
void snd_pcm_release_substream(struct snd_pcm_substream *substream);
|
void snd_pcm_release_substream(struct snd_pcm_substream *substream);
|
||||||
|
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
|
||||||
|
struct snd_pcm_substream **rsubstream);
|
||||||
|
void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
|
||||||
void snd_pcm_vma_notify_data(void *client, void *data);
|
void snd_pcm_vma_notify_data(void *client, void *data);
|
||||||
int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
|
int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ struct snd_pcm_oss_file {
|
||||||
struct snd_pcm_oss_substream {
|
struct snd_pcm_oss_substream {
|
||||||
unsigned oss: 1; /* oss mode */
|
unsigned oss: 1; /* oss mode */
|
||||||
struct snd_pcm_oss_setup *setup; /* active setup */
|
struct snd_pcm_oss_setup *setup; /* active setup */
|
||||||
struct snd_pcm_oss_file *file;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct snd_pcm_oss_stream {
|
struct snd_pcm_oss_stream {
|
||||||
|
|
|
@ -1671,6 +1671,18 @@ static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_pcm_runtime *runtime;
|
||||||
|
runtime = substream->runtime;
|
||||||
|
vfree(runtime->oss.buffer);
|
||||||
|
runtime->oss.buffer = NULL;
|
||||||
|
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
|
||||||
|
snd_pcm_oss_plugin_clear(substream);
|
||||||
|
#endif
|
||||||
|
substream->oss.oss = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
|
static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_oss_setup *setup,
|
struct snd_pcm_oss_setup *setup,
|
||||||
int minor)
|
int minor)
|
||||||
|
@ -1679,6 +1691,10 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
substream->oss.oss = 1;
|
substream->oss.oss = 1;
|
||||||
substream->oss.setup = setup;
|
substream->oss.setup = setup;
|
||||||
|
if (setup->nonblock)
|
||||||
|
substream->ffile->f_flags |= O_NONBLOCK;
|
||||||
|
else
|
||||||
|
substream->ffile->f_flags &= ~O_NONBLOCK;
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
runtime->oss.params = 1;
|
runtime->oss.params = 1;
|
||||||
runtime->oss.trigger = 1;
|
runtime->oss.trigger = 1;
|
||||||
|
@ -1697,18 +1713,7 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
|
||||||
runtime->oss.fragshift = 0;
|
runtime->oss.fragshift = 0;
|
||||||
runtime->oss.maxfrags = 0;
|
runtime->oss.maxfrags = 0;
|
||||||
runtime->oss.subdivision = 0;
|
runtime->oss.subdivision = 0;
|
||||||
}
|
substream->pcm_release = snd_pcm_oss_release_substream;
|
||||||
|
|
||||||
static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
|
|
||||||
{
|
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
runtime = substream->runtime;
|
|
||||||
vfree(runtime->oss.buffer);
|
|
||||||
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
|
|
||||||
snd_pcm_oss_plugin_clear(substream);
|
|
||||||
#endif
|
|
||||||
substream->oss.file = NULL;
|
|
||||||
substream->oss.oss = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
|
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
|
||||||
|
@ -1717,23 +1722,8 @@ static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
|
||||||
snd_assert(pcm_oss_file != NULL, return -ENXIO);
|
snd_assert(pcm_oss_file != NULL, return -ENXIO);
|
||||||
for (cidx = 0; cidx < 2; ++cidx) {
|
for (cidx = 0; cidx < 2; ++cidx) {
|
||||||
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
|
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
|
||||||
struct snd_pcm_runtime *runtime;
|
if (substream)
|
||||||
if (substream == NULL)
|
snd_pcm_release_substream(substream);
|
||||||
continue;
|
|
||||||
runtime = substream->runtime;
|
|
||||||
|
|
||||||
snd_pcm_stream_lock_irq(substream);
|
|
||||||
if (snd_pcm_running(substream))
|
|
||||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
|
|
||||||
snd_pcm_stream_unlock_irq(substream);
|
|
||||||
if (substream->ffile != NULL) {
|
|
||||||
if (substream->ops->hw_free != NULL)
|
|
||||||
substream->ops->hw_free(substream);
|
|
||||||
substream->ops->close(substream);
|
|
||||||
substream->ffile = NULL;
|
|
||||||
}
|
|
||||||
snd_pcm_oss_release_substream(substream);
|
|
||||||
snd_pcm_release_substream(substream);
|
|
||||||
}
|
}
|
||||||
kfree(pcm_oss_file);
|
kfree(pcm_oss_file);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1743,12 +1733,11 @@ static int snd_pcm_oss_open_file(struct file *file,
|
||||||
struct snd_pcm *pcm,
|
struct snd_pcm *pcm,
|
||||||
struct snd_pcm_oss_file **rpcm_oss_file,
|
struct snd_pcm_oss_file **rpcm_oss_file,
|
||||||
int minor,
|
int minor,
|
||||||
struct snd_pcm_oss_setup *psetup,
|
struct snd_pcm_oss_setup **setup)
|
||||||
struct snd_pcm_oss_setup *csetup)
|
|
||||||
{
|
{
|
||||||
int err = 0;
|
int idx, err;
|
||||||
struct snd_pcm_oss_file *pcm_oss_file;
|
struct snd_pcm_oss_file *pcm_oss_file;
|
||||||
struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
|
struct snd_pcm_substream *substream;
|
||||||
unsigned int f_mode = file->f_mode;
|
unsigned int f_mode = file->f_mode;
|
||||||
|
|
||||||
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
|
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
|
||||||
|
@ -1761,73 +1750,31 @@ static int snd_pcm_oss_open_file(struct file *file,
|
||||||
if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
|
if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
|
||||||
(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
|
(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
|
||||||
f_mode = FMODE_WRITE;
|
f_mode = FMODE_WRITE;
|
||||||
if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
|
|
||||||
if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
for (idx = 0; idx < 2; idx++) {
|
||||||
&psubstream)) < 0) {
|
if (! setup[idx] || setup[idx]->disable)
|
||||||
|
continue;
|
||||||
|
if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
if (! (f_mode & FMODE_WRITE))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (! (f_mode & FMODE_READ))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
err = snd_pcm_open_substream(pcm, idx, file, &substream);
|
||||||
|
if (err < 0) {
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
snd_pcm_oss_release_file(pcm_oss_file);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
|
|
||||||
}
|
pcm_oss_file->streams[idx] = substream;
|
||||||
if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
|
snd_pcm_oss_init_substream(substream, setup[idx], minor);
|
||||||
if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE,
|
|
||||||
&csubstream)) < 0) {
|
|
||||||
if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
} else {
|
|
||||||
csubstream = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psubstream == NULL && csubstream == NULL) {
|
if (! pcm_oss_file->streams[0] && pcm_oss_file->streams[1]) {
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
snd_pcm_oss_release_file(pcm_oss_file);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (psubstream != NULL) {
|
|
||||||
psubstream->oss.file = pcm_oss_file;
|
|
||||||
err = snd_pcm_hw_constraints_init(psubstream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraint_init failed\n");
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if ((err = psubstream->ops->open(psubstream)) < 0) {
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
psubstream->ffile = file;
|
|
||||||
err = snd_pcm_hw_constraints_complete(psubstream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraint_complete failed\n");
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
snd_pcm_oss_init_substream(psubstream, psetup, minor);
|
|
||||||
}
|
|
||||||
if (csubstream != NULL) {
|
|
||||||
csubstream->oss.file = pcm_oss_file;
|
|
||||||
err = snd_pcm_hw_constraints_init(csubstream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraint_init failed\n");
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if ((err = csubstream->ops->open(csubstream)) < 0) {
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
csubstream->ffile = file;
|
|
||||||
err = snd_pcm_hw_constraints_complete(csubstream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraint_complete failed\n");
|
|
||||||
snd_pcm_oss_release_file(pcm_oss_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
snd_pcm_oss_init_substream(csubstream, csetup, minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
file->private_data = pcm_oss_file;
|
file->private_data = pcm_oss_file;
|
||||||
*rpcm_oss_file = pcm_oss_file;
|
*rpcm_oss_file = pcm_oss_file;
|
||||||
|
@ -1852,7 +1799,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
||||||
char task_name[32];
|
char task_name[32];
|
||||||
struct snd_pcm *pcm;
|
struct snd_pcm *pcm;
|
||||||
struct snd_pcm_oss_file *pcm_oss_file;
|
struct snd_pcm_oss_file *pcm_oss_file;
|
||||||
struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
|
struct snd_pcm_oss_setup *setup[2];
|
||||||
int nonblock;
|
int nonblock;
|
||||||
wait_queue_t wait;
|
wait_queue_t wait;
|
||||||
|
|
||||||
|
@ -1873,23 +1820,13 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto __error;
|
goto __error;
|
||||||
}
|
}
|
||||||
|
memset(setup, 0, sizeof(*setup));
|
||||||
if (file->f_mode & FMODE_WRITE)
|
if (file->f_mode & FMODE_WRITE)
|
||||||
psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
|
setup[0] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
|
||||||
if (file->f_mode & FMODE_READ)
|
if (file->f_mode & FMODE_READ)
|
||||||
csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
|
setup[1] = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
|
||||||
|
|
||||||
nonblock = !!(file->f_flags & O_NONBLOCK);
|
nonblock = !!(file->f_flags & O_NONBLOCK);
|
||||||
if (psetup && !psetup->disable) {
|
|
||||||
if (psetup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (psetup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
} else if (csetup && !csetup->disable) {
|
|
||||||
if (csetup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (csetup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
}
|
|
||||||
if (!nonblock)
|
if (!nonblock)
|
||||||
nonblock = nonblock_open;
|
nonblock = nonblock_open;
|
||||||
|
|
||||||
|
@ -1898,7 +1835,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
||||||
mutex_lock(&pcm->open_mutex);
|
mutex_lock(&pcm->open_mutex);
|
||||||
while (1) {
|
while (1) {
|
||||||
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
|
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
|
||||||
iminor(inode), psetup, csetup);
|
iminor(inode), setup);
|
||||||
if (err >= 0)
|
if (err >= 0)
|
||||||
break;
|
break;
|
||||||
if (err == -EAGAIN) {
|
if (err == -EAGAIN) {
|
||||||
|
|
|
@ -777,8 +777,9 @@ static void snd_pcm_tick_timer_func(unsigned long data)
|
||||||
snd_pcm_tick_elapsed(substream);
|
snd_pcm_tick_elapsed(substream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
|
||||||
struct snd_pcm_substream **rsubstream)
|
struct file *file,
|
||||||
|
struct snd_pcm_substream **rsubstream)
|
||||||
{
|
{
|
||||||
struct snd_pcm_str * pstr;
|
struct snd_pcm_str * pstr;
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
|
@ -793,7 +794,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
||||||
*rsubstream = NULL;
|
*rsubstream = NULL;
|
||||||
snd_assert(pcm != NULL, return -ENXIO);
|
snd_assert(pcm != NULL, return -ENXIO);
|
||||||
pstr = &pcm->streams[stream];
|
pstr = &pcm->streams[stream];
|
||||||
if (pstr->substream == NULL)
|
if (pstr->substream == NULL || pstr->substream_count == 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
card = pcm->card;
|
card = pcm->card;
|
||||||
|
@ -807,8 +808,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
||||||
}
|
}
|
||||||
up_read(&card->controls_rwsem);
|
up_read(&card->controls_rwsem);
|
||||||
|
|
||||||
if (pstr->substream_count == 0)
|
|
||||||
return -ENODEV;
|
|
||||||
switch (stream) {
|
switch (stream) {
|
||||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||||
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
|
if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
|
||||||
|
@ -874,12 +873,13 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
||||||
|
|
||||||
substream->runtime = runtime;
|
substream->runtime = runtime;
|
||||||
substream->private_data = pcm->private_data;
|
substream->private_data = pcm->private_data;
|
||||||
|
substream->ffile = file;
|
||||||
pstr->substream_opened++;
|
pstr->substream_opened++;
|
||||||
*rsubstream = substream;
|
*rsubstream = substream;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void snd_pcm_release_substream(struct snd_pcm_substream *substream)
|
void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime;
|
struct snd_pcm_runtime *runtime;
|
||||||
substream->file = NULL;
|
substream->file = NULL;
|
||||||
|
|
|
@ -2299,19 +2299,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
snd_assert(substream->ffile != NULL, return -ENXIO);
|
|
||||||
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
|
||||||
if (substream->oss.oss) {
|
|
||||||
struct snd_pcm_oss_setup *setup = substream->oss.setup;
|
|
||||||
if (setup != NULL) {
|
|
||||||
if (setup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (setup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
|
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
|
||||||
runtime->channels > 1)
|
runtime->channels > 1)
|
||||||
|
@ -2374,19 +2362,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
snd_assert(substream->ffile != NULL, return -ENXIO);
|
|
||||||
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
|
||||||
if (substream->oss.oss) {
|
|
||||||
struct snd_pcm_oss_setup *setup = substream->oss.setup;
|
|
||||||
if (setup != NULL) {
|
|
||||||
if (setup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (setup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2596,19 +2572,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
snd_assert(substream->ffile != NULL, return -ENXIO);
|
|
||||||
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
|
||||||
if (substream->oss.oss) {
|
|
||||||
struct snd_pcm_oss_setup *setup = substream->oss.setup;
|
|
||||||
if (setup != NULL) {
|
|
||||||
if (setup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (setup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
|
if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
|
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
|
||||||
|
@ -2665,20 +2629,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
|
||||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
||||||
return -EBADFD;
|
return -EBADFD;
|
||||||
|
|
||||||
snd_assert(substream->ffile != NULL, return -ENXIO);
|
|
||||||
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
|
||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
|
|
||||||
if (substream->oss.oss) {
|
|
||||||
struct snd_pcm_oss_setup *setup = substream->oss.setup;
|
|
||||||
if (setup != NULL) {
|
|
||||||
if (setup->nonblock)
|
|
||||||
nonblock = 1;
|
|
||||||
else if (setup->block)
|
|
||||||
nonblock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
|
return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
|
||||||
|
|
|
@ -1995,28 +1995,63 @@ static void snd_pcm_remove_file(struct snd_pcm_str *str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
|
static void pcm_release_private(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_file *pcm_file = substream->file;
|
||||||
struct snd_pcm_runtime *runtime;
|
|
||||||
struct snd_pcm_str * str;
|
|
||||||
|
|
||||||
snd_assert(pcm_file != NULL, return -ENXIO);
|
|
||||||
substream = pcm_file->substream;
|
|
||||||
snd_assert(substream != NULL, return -ENXIO);
|
|
||||||
runtime = substream->runtime;
|
|
||||||
str = substream->pstr;
|
|
||||||
snd_pcm_unlink(substream);
|
snd_pcm_unlink(substream);
|
||||||
if (substream->ffile != NULL) {
|
snd_pcm_remove_file(substream->pstr, pcm_file);
|
||||||
|
kfree(pcm_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snd_pcm_release_substream(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
snd_pcm_drop(substream);
|
||||||
|
if (substream->pcm_release)
|
||||||
|
substream->pcm_release(substream);
|
||||||
|
if (substream->hw_opened) {
|
||||||
if (substream->ops->hw_free != NULL)
|
if (substream->ops->hw_free != NULL)
|
||||||
substream->ops->hw_free(substream);
|
substream->ops->hw_free(substream);
|
||||||
substream->ops->close(substream);
|
substream->ops->close(substream);
|
||||||
substream->ffile = NULL;
|
substream->hw_opened = 0;
|
||||||
}
|
}
|
||||||
snd_pcm_remove_file(str, pcm_file);
|
snd_pcm_detach_substream(substream);
|
||||||
snd_pcm_release_substream(substream);
|
}
|
||||||
kfree(pcm_file);
|
|
||||||
|
int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
|
||||||
|
struct file *file,
|
||||||
|
struct snd_pcm_substream **rsubstream)
|
||||||
|
{
|
||||||
|
struct snd_pcm_substream *substream;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = snd_pcm_attach_substream(pcm, stream, file, &substream);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
substream->no_mmap_ctrl = 0;
|
||||||
|
err = snd_pcm_hw_constraints_init(substream);
|
||||||
|
if (err < 0) {
|
||||||
|
snd_printd("snd_pcm_hw_constraints_init failed\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = substream->ops->open(substream)) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
substream->hw_opened = 1;
|
||||||
|
|
||||||
|
err = snd_pcm_hw_constraints_complete(substream);
|
||||||
|
if (err < 0) {
|
||||||
|
snd_printd("snd_pcm_hw_constraints_complete failed\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rsubstream = substream;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
snd_pcm_release_substream(substream);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_open_file(struct file *file,
|
static int snd_pcm_open_file(struct file *file,
|
||||||
|
@ -2024,52 +2059,29 @@ static int snd_pcm_open_file(struct file *file,
|
||||||
int stream,
|
int stream,
|
||||||
struct snd_pcm_file **rpcm_file)
|
struct snd_pcm_file **rpcm_file)
|
||||||
{
|
{
|
||||||
int err = 0;
|
|
||||||
struct snd_pcm_file *pcm_file;
|
struct snd_pcm_file *pcm_file;
|
||||||
struct snd_pcm_substream *substream;
|
struct snd_pcm_substream *substream;
|
||||||
struct snd_pcm_str *str;
|
struct snd_pcm_str *str;
|
||||||
|
int err;
|
||||||
|
|
||||||
snd_assert(rpcm_file != NULL, return -EINVAL);
|
snd_assert(rpcm_file != NULL, return -EINVAL);
|
||||||
*rpcm_file = NULL;
|
*rpcm_file = NULL;
|
||||||
|
|
||||||
|
err = snd_pcm_open_substream(pcm, stream, file, &substream);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
|
pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
|
||||||
if (pcm_file == NULL) {
|
if (pcm_file == NULL) {
|
||||||
|
snd_pcm_release_substream(substream);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
|
|
||||||
kfree(pcm_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = substream->pstr;
|
str = substream->pstr;
|
||||||
substream->file = pcm_file;
|
substream->file = pcm_file;
|
||||||
substream->no_mmap_ctrl = 0;
|
substream->pcm_release = pcm_release_private;
|
||||||
|
|
||||||
pcm_file->substream = substream;
|
pcm_file->substream = substream;
|
||||||
|
|
||||||
snd_pcm_add_file(str, pcm_file);
|
snd_pcm_add_file(str, pcm_file);
|
||||||
|
|
||||||
err = snd_pcm_hw_constraints_init(substream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraints_init failed\n");
|
|
||||||
snd_pcm_release_file(pcm_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = substream->ops->open(substream)) < 0) {
|
|
||||||
snd_pcm_release_file(pcm_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
substream->ffile = file;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_constraints_complete(substream);
|
|
||||||
if (err < 0) {
|
|
||||||
snd_printd("snd_pcm_hw_constraints_complete failed\n");
|
|
||||||
snd_pcm_release_file(pcm_file);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
file->private_data = pcm_file;
|
file->private_data = pcm_file;
|
||||||
*rpcm_file = pcm_file;
|
*rpcm_file = pcm_file;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2158,10 +2170,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
|
||||||
snd_assert(substream != NULL, return -ENXIO);
|
snd_assert(substream != NULL, return -ENXIO);
|
||||||
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
|
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
|
||||||
pcm = substream->pcm;
|
pcm = substream->pcm;
|
||||||
snd_pcm_drop(substream);
|
|
||||||
fasync_helper(-1, file, 0, &substream->runtime->fasync);
|
fasync_helper(-1, file, 0, &substream->runtime->fasync);
|
||||||
mutex_lock(&pcm->open_mutex);
|
mutex_lock(&pcm->open_mutex);
|
||||||
snd_pcm_release_file(pcm_file);
|
snd_pcm_release_substream(substream);
|
||||||
mutex_unlock(&pcm->open_mutex);
|
mutex_unlock(&pcm->open_mutex);
|
||||||
wake_up(&pcm->open_wait);
|
wake_up(&pcm->open_wait);
|
||||||
module_put(pcm->card->module);
|
module_put(pcm->card->module);
|
||||||
|
@ -2480,11 +2491,6 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
|
|
||||||
unsigned int cmd, void __user *arg);
|
|
||||||
static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
|
|
||||||
unsigned int cmd, void __user *arg);
|
|
||||||
|
|
||||||
static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
|
static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
|
||||||
unsigned int cmd, void __user *arg)
|
unsigned int cmd, void __user *arg)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue