set_fs(fs);
}
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
}
return 0;
}
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
{
oss_buffer_size = runtime->oss.mmap_bytes;
}
- if (substream->oss.setup &&
- substream->oss.setup->period_size > 16)
- oss_period_size = substream->oss.setup->period_size;
+ if (substream->oss.setup.period_size > 16)
+ oss_period_size = substream->oss.setup.period_size;
else if (runtime->oss.fragshift) {
oss_period_size = 1 << runtime->oss.fragshift;
if (oss_period_size > oss_buffer_size / 2)
oss_periods = oss_buffer_size / oss_period_size;
- if (substream->oss.setup) {
- if (substream->oss.setup->periods > 1)
- oss_periods = substream->oss.setup->periods;
- }
+ if (substream->oss.setup.periods > 1)
+ oss_periods = substream->oss.setup.periods;
s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
goto failure;
}
- if (atomic_read(&runtime->mmap_count)) {
+ if (atomic_read(&runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
_snd_pcm_hw_params_any(sparams);
_snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
oss_frame_size = snd_pcm_format_physical_width(params_format(params)) *
params_channels(params) / 8;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
snd_pcm_oss_plugin_clear(substream);
if (!direct) {
/* add necessary plugins */
}
}
}
+#endif
err = snd_pcm_oss_period_size(substream, params, sparams);
if (err < 0)
1 : runtime->period_size;
sw_params->xfer_align = 1;
if (atomic_read(&runtime->mmap_count) ||
- (substream->oss.setup && substream->oss.setup->nosilence)) {
+ substream->oss.setup.nosilence) {
sw_params->silence_threshold = 0;
sw_params->silence_size = 0;
} else {
runtime->oss.periods = params_periods(sparams);
oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams));
snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure);
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first) {
err = snd_pcm_plug_alloc(substream, oss_period_size);
if (err < 0)
goto failure;
}
+#endif
oss_period_size *= oss_frame_size;
oss_buffer_size = oss_period_size * runtime->oss.periods;
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first) {
struct snd_pcm_plugin_channel *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
if (frames1 <= 0)
return frames1;
bytes = frames1 * oss_frame_bytes;
- } else {
+ } else
+#endif
+ {
frames = bytes_to_frames(runtime, bytes);
frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);
if (frames1 <= 0)
buf += tmp;
bytes -= tmp;
xfer += tmp;
- if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
+ if (substream->oss.setup.partialfrag ||
runtime->oss.buffer_used == runtime->oss.period_bytes) {
tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
struct snd_pcm_plugin_channel *channels;
bytes = frames1 * oss_frame_bytes;
if (!in_kernel && copy_to_user(final_dst, buf, bytes))
return -EFAULT;
- } else {
+ } else
+#endif
+ {
frames = bytes_to_frames(runtime, bytes);
frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);
if (frames1 <= 0)
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) {
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
if (substream != NULL) {
- snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
substream->runtime->oss.prepare = 1;
}
return 0;
if (substream != NULL) {
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
- snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
}
/* note: all errors from the start action are ignored */
/* OSS apps do not know, how to handle them */
__direct:
saved_f_flags = substream->ffile->f_flags;
substream->ffile->f_flags &= ~O_NONBLOCK;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
substream->ffile->f_flags = saved_f_flags;
if (err < 0)
return err;
if ((err = snd_pcm_oss_make_ready(substream)) < 0)
return err;
runtime = substream->runtime;
- err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (err < 0)
return err;
runtime->oss.buffer_used = 0;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
return err;
- if (atomic_read(&substream->runtime->mmap_count)) {
+ if (atomic_read(&substream->runtime->mmap_count))
direct = 1;
- } else {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- direct = (setup != NULL && setup->direct);
- }
+ else
+ direct = substream->oss.setup.direct;
if (!direct)
return AFMT_MU_LAW | AFMT_U8 |
AFMT_S16_LE | AFMT_S16_BE |
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
if (err < 0)
return err;
}
cmd = SNDRV_PCM_IOCTL_DROP;
runtime->oss.prepare = 1;
}
- err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL);
+ err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
if (err < 0)
return err;
}
runtime = substream->runtime;
if (runtime->oss.params || runtime->oss.prepare)
return 0;
- err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
if (err == -EPIPE)
delay = 0; /* hack for broken OSS applications */
else if (err < 0)
} else {
delay = snd_pcm_oss_bytes(substream, delay);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- struct snd_pcm_oss_setup *setup = substream->oss.setup;
- if (setup && setup->buggyptr)
+ if (substream->oss.setup.buggyptr)
info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
else
info.blocks = (delay + fixup) / runtime->oss.period_bytes;
return -EINVAL;
}
-static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
+static const char *strip_task_path(const char *path)
{
- const char *ptr, *ptrl;
- struct snd_pcm_oss_setup *setup;
-
- down(&pcm->streams[stream].oss.setup_mutex);
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, task_name)) {
- up(&pcm->streams[stream].oss.setup_mutex);
- return setup;
- }
- }
- ptr = ptrl = task_name;
- while (*ptr) {
+ const char *ptr, *ptrl = NULL;
+ for (ptr = path; *ptr; ptr++) {
if (*ptr == '/')
ptrl = ptr + 1;
- ptr++;
}
- if (ptrl == task_name) {
- goto __not_found;
- return NULL;
- }
- for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
- if (!strcmp(setup->task_name, ptrl)) {
- up(&pcm->streams[stream].oss.setup_mutex);
- return setup;
+ return ptrl;
+}
+
+static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
+ const char *task_name,
+ struct snd_pcm_oss_setup *rsetup)
+{
+ struct snd_pcm_oss_setup *setup;
+
+ mutex_lock(&pcm->streams[stream].oss.setup_mutex);
+ do {
+ for (setup = pcm->streams[stream].oss.setup_list; setup;
+ setup = setup->next) {
+ if (!strcmp(setup->task_name, task_name))
+ goto out;
}
- }
- __not_found:
- up(&pcm->streams[stream].oss.setup_mutex);
- return NULL;
+ } while ((task_name = strip_task_path(task_name)) != NULL);
+ out:
+ if (setup)
+ *rsetup = *setup;
+ mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
+}
+
+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,
struct snd_pcm_runtime *runtime;
substream->oss.oss = 1;
- substream->oss.setup = setup;
+ substream->oss.setup = *setup;
+ if (setup->nonblock)
+ substream->ffile->f_flags |= O_NONBLOCK;
+ else if (setup->block)
+ substream->ffile->f_flags &= ~O_NONBLOCK;
runtime = substream->runtime;
runtime->oss.params = 1;
runtime->oss.trigger = 1;
runtime->oss.fragshift = 0;
runtime->oss.maxfrags = 0;
runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime;
- runtime = substream->runtime;
- vfree(runtime->oss.buffer);
- snd_pcm_oss_plugin_clear(substream);
- substream->oss.file = NULL;
- substream->oss.oss = 0;
+ substream->pcm_release = snd_pcm_oss_release_substream;
}
static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
snd_assert(pcm_oss_file != NULL, return -ENXIO);
for (cidx = 0; cidx < 2; ++cidx) {
struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
- struct snd_pcm_runtime *runtime;
- if (substream == NULL)
- 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);
+ if (substream)
+ snd_pcm_release_substream(substream);
}
kfree(pcm_oss_file);
return 0;
struct snd_pcm *pcm,
struct snd_pcm_oss_file **rpcm_oss_file,
int minor,
- struct snd_pcm_oss_setup *psetup,
- struct snd_pcm_oss_setup *csetup)
+ struct snd_pcm_oss_setup *setup)
{
- int err = 0;
+ int idx, err;
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;
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
f_mode = FMODE_WRITE;
- if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
- if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &psubstream)) < 0) {
+
+ for (idx = 0; idx < 2; idx++) {
+ if (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);
return err;
}
- pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
- }
- if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
- 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;
+
+ pcm_oss_file->streams[idx] = substream;
+ substream->file = pcm_oss_file;
+ snd_pcm_oss_init_substream(substream, &setup[idx], minor);
}
- if (psubstream == NULL && csubstream == NULL) {
+ if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
snd_pcm_oss_release_file(pcm_oss_file);
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;
*rpcm_oss_file = pcm_oss_file;
char task_name[32];
struct snd_pcm *pcm;
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;
wait_queue_t wait;
err = -EFAULT;
goto __error;
}
+ memset(setup, 0, sizeof(setup));
if (file->f_mode & FMODE_WRITE)
- psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ task_name, &setup[0]);
if (file->f_mode & FMODE_READ)
- csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+ snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ task_name, &setup[1]);
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)
nonblock = nonblock_open;
init_waitqueue_entry(&wait, current);
add_wait_queue(&pcm->open_wait, &wait);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
- iminor(inode), psetup, csetup);
+ iminor(inode), setup);
if (err >= 0)
break;
if (err == -EAGAIN) {
} else
break;
set_current_state(TASK_INTERRUPTIBLE);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
schedule();
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}
}
remove_wait_queue(&pcm->open_wait, &wait);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
if (err < 0)
goto __error;
return err;
snd_assert(substream != NULL, return -ENXIO);
pcm = substream->pcm;
snd_pcm_oss_sync(pcm_oss_file);
- down(&pcm->open_mutex);
+ mutex_lock(&pcm->open_mutex);
snd_pcm_oss_release_file(pcm_oss_file);
- up(&pcm->open_mutex);
+ mutex_unlock(&pcm->open_mutex);
wake_up(&pcm->open_wait);
module_put(pcm->card->module);
snd_card_file_remove(pcm->card, file);
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream == NULL)
return -ENXIO;
- up(&file->f_dentry->d_inode->i_sem);
result = snd_pcm_oss_write1(substream, buf, count);
- down(&file->f_dentry->d_inode->i_sem);
#ifdef OSS_DEBUG
printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
#endif
if ((err = snd_pcm_oss_change_params(substream)) < 0)
return err;
}
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
if (runtime->oss.plugin_first != NULL)
return -EIO;
+#endif
if (area->vm_pgoff != 0)
return -EINVAL;
{
struct snd_pcm_str *pstr = entry->private_data;
struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
- down(&pstr->oss.setup_mutex);
+ mutex_lock(&pstr->oss.setup_mutex);
while (setup) {
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
setup->task_name,
setup->nosilence ? " no-silence" : "");
setup = setup->next;
}
- up(&pstr->oss.setup_mutex);
+ mutex_unlock(&pstr->oss.setup_mutex);
}
static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
{
- unsigned int idx;
- struct snd_pcm_substream *substream;
struct snd_pcm_oss_setup *setup, *setupn;
- for (idx = 0, substream = pstr->substream;
- idx < pstr->substream_count; idx++, substream = substream->next)
- substream->oss.setup = NULL;
for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
setup; setup = setupn) {
setupn = setup->next;
struct snd_pcm_oss_setup *setup, *setup1, template;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
- down(&pstr->oss.setup_mutex);
+ mutex_lock(&pstr->oss.setup_mutex);
memset(&template, 0, sizeof(template));
ptr = snd_info_get_str(task_name, line, sizeof(task_name));
if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
snd_pcm_oss_proc_free_setup_list(pstr);
- up(&pstr->oss.setup_mutex);
+ mutex_unlock(&pstr->oss.setup_mutex);
continue;
}
for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
}
} while (*str);
if (setup == NULL) {
- setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
- if (setup) {
- if (pstr->oss.setup_list == NULL) {
- pstr->oss.setup_list = setup;
- } else {
- for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
- setup1->next = setup;
- }
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- } else {
+ setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+ if (! setup) {
+ buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
+ }
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+ for (setup1 = pstr->oss.setup_list;
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
+ if (! template.task_name) {
+ kfree(setup);
buffer->error = -ENOMEM;
+ mutex_lock(&pstr->oss.setup_mutex);
+ return;
}
}
- if (setup)
- *setup = template;
- up(&pstr->oss.setup_mutex);
+ *setup = template;
+ mutex_unlock(&pstr->oss.setup_mutex);
}
}