X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Foss%2Fpcm_oss.c;h=7f393a024b0934232e9ec0d65ccb3916d42c57d2;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=099d230f3e0715e3bb931d1927578ef5c0f5c872;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 099d230f3..7f393a024 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -28,10 +28,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -45,28 +47,24 @@ static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static int nonblock_open; -static int boot_devs; +static int nonblock_open = 1; MODULE_AUTHOR("Jaroslav Kysela , Abramo Bagnara "); MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); MODULE_LICENSE("GPL"); -module_param_array(dsp_map, int, boot_devs, 0444); +module_param_array(dsp_map, int, NULL, 0444); MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device."); -MODULE_PARM_SYNTAX(dsp_map, "default:0,skill:advanced"); -module_param_array(adsp_map, int, boot_devs, 0444); +module_param_array(adsp_map, int, NULL, 0444); MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device."); -MODULE_PARM_SYNTAX(adsp_map, "default:1,skill:advanced"); module_param(nonblock_open, bool, 0644); MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); -MODULE_PARM_SYNTAX(nonblock_open, "default:0,skill:advanced"); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); -extern int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg); -static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file); -static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file); -static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file); +extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg); +static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); +static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); +static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); static inline mm_segment_t snd_enter_user(void) { @@ -80,10 +78,11 @@ static inline void snd_leave_user(mm_segment_t fs) set_fs(fs); } -int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) +#ifdef CONFIG_SND_PCM_OSS_PLUGINS +static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_pcm_plugin_t *plugin, *next; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_plugin *plugin, *next; plugin = runtime->oss.plugin_first; while (plugin) { @@ -95,9 +94,9 @@ int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) return 0; } -int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) +static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin) { - snd_pcm_runtime_t *runtime = plugin->plug->runtime; + struct snd_pcm_runtime *runtime = plugin->plug->runtime; plugin->next = runtime->oss.plugin_first; plugin->prev = NULL; if (runtime->oss.plugin_first) { @@ -110,9 +109,9 @@ int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) return 0; } -int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) +int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin) { - snd_pcm_runtime_t *runtime = plugin->plug->runtime; + struct snd_pcm_runtime *runtime = plugin->plug->runtime; plugin->next = NULL; plugin->prev = runtime->oss.plugin_last; if (runtime->oss.plugin_last) { @@ -124,21 +123,31 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) } return 0; } +#endif /* CONFIG_SND_PCM_OSS_PLUGINS */ -static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames) +static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); - frames = frames_to_bytes(runtime, frames); + struct snd_pcm_runtime *runtime = substream->runtime; + long buffer_size = snd_pcm_lib_buffer_bytes(substream); + long bytes = frames_to_bytes(runtime, frames); if (buffer_size == runtime->oss.buffer_bytes) - return frames; - return (runtime->oss.buffer_bytes * frames) / buffer_size; + return bytes; +#if BITS_PER_LONG >= 64 + return runtime->oss.buffer_bytes * bytes / buffer_size; +#else + { + u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; + u32 rem; + div64_32(&bsize, buffer_size, &rem); + return (long)bsize; + } +#endif } -static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) +static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + long buffer_size = snd_pcm_lib_buffer_bytes(substream); if (buffer_size == runtime->oss.buffer_bytes) return bytes_to_frames(runtime, bytes); return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); @@ -178,14 +187,14 @@ static int snd_pcm_oss_format_to(int format) } } -static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t *oss_params, - snd_pcm_hw_params_t *slave_params) +static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *oss_params, + struct snd_pcm_hw_params *slave_params) { size_t s; size_t oss_buffer_size, oss_period_size, oss_periods; size_t min_period_size, max_period_size; - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; size_t oss_frame_size; oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * @@ -199,9 +208,8 @@ static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream, 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) @@ -243,10 +251,8 @@ static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream, 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) @@ -270,11 +276,11 @@ static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream, return 0; } -static int choose_rate(snd_pcm_substream_t *substream, - snd_pcm_hw_params_t *params, unsigned int best_rate) +static int choose_rate(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, unsigned int best_rate) { - snd_interval_t *it; - snd_pcm_hw_params_t *save; + struct snd_interval *it; + struct snd_pcm_hw_params *save; unsigned int rate, prev; save = kmalloc(sizeof(*save), GFP_KERNEL); @@ -310,18 +316,18 @@ static int choose_rate(snd_pcm_substream_t *substream, return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); } -static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) +static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) { - snd_pcm_runtime_t *runtime = substream->runtime; - snd_pcm_hw_params_t *params, *sparams; - snd_pcm_sw_params_t *sw_params; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hw_params *params, *sparams; + struct snd_pcm_sw_params *sw_params; ssize_t oss_buffer_size, oss_period_size; size_t oss_frame_size; int err; int direct; int format, sformat, n; - snd_mask_t sformat_mask; - snd_mask_t mask; + struct snd_mask sformat_mask; + struct snd_mask mask; sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL); @@ -332,12 +338,10 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) goto failure; } - if (atomic_read(&runtime->mmap_count)) { + if (atomic_read(&runtime->mmap_count)) direct = 1; - } else { - snd_pcm_oss_setup_t *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); @@ -405,6 +409,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) 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 */ @@ -417,7 +422,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) goto failure; } if (runtime->oss.plugin_first) { - snd_pcm_plugin_t *plugin; + struct snd_pcm_plugin *plugin; if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { snd_printd("snd_pcm_plugin_build_io failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); @@ -434,6 +439,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) } } } +#endif err = snd_pcm_oss_period_size(substream, params, sparams); if (err < 0) @@ -467,10 +473,11 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; sw_params->period_step = 1; sw_params->sleep_min = 0; - sw_params->avail_min = 1; + sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + 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 { @@ -490,11 +497,13 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) 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; @@ -516,8 +525,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) runtime->oss.params = 0; runtime->oss.prepare = 1; - if (runtime->oss.buffer != NULL) - vfree(runtime->oss.buffer); + vfree(runtime->oss.buffer); runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); runtime->oss.buffer_used = 0; if (runtime->dma_area) @@ -527,19 +535,16 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) err = 0; failure: - if (sw_params) - kfree(sw_params); - if (params) - kfree(params); - if (sparams) - kfree(sparams); + kfree(sw_params); + kfree(params); + kfree(sparams); return err; } -static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, snd_pcm_substream_t **r_substream) +static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream) { int idx, err; - snd_pcm_substream_t *asubstream = NULL, *substream; + struct snd_pcm_substream *asubstream = NULL, *substream; for (idx = 0; idx < 2; idx++) { substream = pcm_oss_file->streams[idx]; @@ -559,10 +564,10 @@ static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, sn return 0; } -static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream) +static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) { int err; - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); if (err < 0) { @@ -577,9 +582,9 @@ static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream) return 0; } -static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream) +static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) { - snd_pcm_runtime_t *runtime; + struct snd_pcm_runtime *runtime; int err; if (substream == NULL) @@ -598,9 +603,9 @@ static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream) return 0; } -static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, snd_pcm_sframes_t *delay) +static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay) { - snd_pcm_runtime_t *runtime; + struct snd_pcm_runtime *runtime; snd_pcm_uframes_t frames; int err = 0; @@ -623,9 +628,9 @@ static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, sn return err; } -snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) +snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || @@ -643,10 +648,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_write(substream, ptr, frames); + ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -658,9 +663,9 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char return ret; } -snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) +snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t delay; int ret; while (1) { @@ -686,10 +691,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_read(substream, ptr, frames); + ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); } if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { @@ -705,9 +710,9 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s return ret; } -snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) +snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || @@ -725,10 +730,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_writev(substream, bufs, frames); + ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -741,9 +746,9 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf return ret; } -snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) +snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || @@ -765,10 +770,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_readv(substream, bufs, frames); + ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -776,15 +781,16 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs return ret; } -static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *buf, size_t bytes, int in_kernel) +static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS if (runtime->oss.plugin_first) { - snd_pcm_plugin_channel_t *channels; + 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 (!in_kernel) { - if (copy_from_user(runtime->oss.buffer, buf, bytes)) + if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes)) return -EFAULT; buf = runtime->oss.buffer; } @@ -796,7 +802,9 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu 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) @@ -806,11 +814,11 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu return bytes; } -static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __user *buf, size_t bytes) +static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes) { size_t xfer = 0; ssize_t tmp; - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&runtime->mmap_count)) return -ENXIO; @@ -830,36 +838,47 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u 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.buffer_used, 1); + tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, + runtime->oss.buffer_used - runtime->oss.period_ptr, 1); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; - runtime->oss.buffer_used = 0; runtime->oss.period_ptr += tmp; runtime->oss.period_ptr %= runtime->oss.period_bytes; + if (runtime->oss.period_ptr == 0 || + runtime->oss.period_ptr == runtime->oss.buffer_used) + runtime->oss.buffer_used = 0; + else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) + return xfer > 0 ? xfer : -EAGAIN; } } else { - tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0); + tmp = snd_pcm_oss_write2(substream, + (const char __force *)buf, + runtime->oss.period_bytes, 0); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; buf += tmp; bytes -= tmp; xfer += tmp; + if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && + tmp != runtime->oss.period_bytes) + break; } } return xfer; } -static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size_t bytes, int in_kernel) +static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t frames, frames1; - char *final_dst = buf; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + char __user *final_dst = (char __user *)buf; if (runtime->oss.plugin_first) { - snd_pcm_plugin_channel_t *channels; + struct snd_pcm_plugin_channel *channels; size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; if (!in_kernel) buf = runtime->oss.buffer; @@ -873,7 +892,9 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size 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) @@ -883,11 +904,11 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size return bytes; } -static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *buf, size_t bytes) +static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes) { size_t xfer = 0; ssize_t tmp; - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&runtime->mmap_count)) return -ENXIO; @@ -914,7 +935,8 @@ static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *bu xfer += tmp; runtime->oss.buffer_used -= tmp; } else { - tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0); + tmp = snd_pcm_oss_read2(substream, (char __force *)buf, + runtime->oss.period_bytes, 0); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; @@ -926,42 +948,42 @@ static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *bu return xfer; } -static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; 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; } -static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 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 */ return 0; } -static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size) +static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) { - snd_pcm_runtime_t *runtime; + struct snd_pcm_runtime *runtime; ssize_t result = 0; long res; wait_queue_t wait; @@ -1005,12 +1027,12 @@ static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size) return result; } -static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) { int err = 0; unsigned int saved_f_flags; - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; snd_pcm_format_t format; unsigned long width; size_t size; @@ -1057,6 +1079,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { size = (runtime->frame_bits * size) / 8; while (size > 0) { + mm_segment_t fs; size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; size -= size1; size1 *= 8; @@ -1064,7 +1087,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) snd_pcm_format_set_silence(runtime->format, runtime->oss.buffer, size1); - snd_pcm_lib_write(substream, runtime->oss.buffer, size1); + fs = snd_enter_user(); + snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); + snd_leave_user(fs); } } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { void __user *buffers[runtime->channels]; @@ -1078,7 +1103,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) __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; @@ -1090,7 +1115,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) 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; @@ -1099,13 +1124,13 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) return 0; } -static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate) +static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) { int idx; for (idx = 1; idx >= 0; --idx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_runtime *runtime; if (substream == NULL) continue; runtime = substream->runtime; @@ -1121,9 +1146,9 @@ static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate) return snd_pcm_oss_get_rate(pcm_oss_file); } -static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) @@ -1131,7 +1156,7 @@ static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file) return substream->runtime->oss.rate; } -static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned int channels) +static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels) { int idx; if (channels < 1) @@ -1139,8 +1164,8 @@ static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned i if (channels > 128) return -EINVAL; for (idx = 1; idx >= 0; --idx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_runtime *runtime; if (substream == NULL) continue; runtime = substream->runtime; @@ -1152,9 +1177,9 @@ static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned i return snd_pcm_oss_get_channels(pcm_oss_file); } -static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) @@ -1162,9 +1187,9 @@ static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file) return substream->runtime->oss.channels; } -static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) @@ -1172,32 +1197,35 @@ static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file) return substream->runtime->oss.period_bytes; } -static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; int direct; - snd_pcm_hw_params_t params; + struct snd_pcm_hw_params *params; unsigned int formats = 0; - snd_mask_t format_mask; + struct snd_mask format_mask; int fmt; + 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 { - snd_pcm_oss_setup_t *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 | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE; - _snd_pcm_hw_params_any(¶ms); - err = snd_pcm_hw_refine(substream, ¶ms); + params = kmalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return -ENOMEM; + _snd_pcm_hw_params_any(params); + err = snd_pcm_hw_refine(substream, params); + format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + kfree(params); snd_assert(err >= 0, return err); - format_mask = *hw_param_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT); for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(&format_mask, fmt)) { int f = snd_pcm_oss_format_to(fmt); @@ -1208,17 +1236,19 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) return formats; } -static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format) +static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) { int formats, idx; if (format != AFMT_QUERY) { formats = snd_pcm_oss_get_formats(pcm_oss_file); + if (formats < 0) + return formats; if (!(formats & format)) format = AFMT_U8; for (idx = 1; idx >= 0; --idx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_runtime *runtime; if (substream == NULL) continue; runtime = substream->runtime; @@ -1231,9 +1261,9 @@ static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format) return snd_pcm_oss_get_format(pcm_oss_file); } -static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) @@ -1241,9 +1271,9 @@ static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file) return substream->runtime->oss.format; } -static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdivide) +static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide) { - snd_pcm_runtime_t *runtime; + struct snd_pcm_runtime *runtime; if (substream == NULL) return 0; @@ -1264,12 +1294,12 @@ static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdiv return subdivide; } -static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdivide) +static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide) { int err = -EINVAL, idx; for (idx = 1; idx >= 0; --idx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; if (substream == NULL) continue; if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) @@ -1278,9 +1308,9 @@ static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdi return err; } -static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned int val) +static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) { - snd_pcm_runtime_t *runtime; + struct snd_pcm_runtime *runtime; if (substream == NULL) return 0; @@ -1297,12 +1327,12 @@ static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned in return 0; } -static int snd_pcm_oss_set_fragment(snd_pcm_oss_file_t *pcm_oss_file, unsigned int val) +static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val) { int err = -EINVAL, idx; for (idx = 1; idx >= 0; --idx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; if (substream == NULL) continue; if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) @@ -1317,7 +1347,7 @@ static int snd_pcm_oss_nonblock(struct file * file) return 0; } -static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res) +static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res) { if (substream == NULL) { @@ -1333,7 +1363,7 @@ static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res) /* all ALSA drivers can return actual pointer in ring buffer */ #if defined(DSP_CAP_REALTIME) && 0 { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) res &= ~DSP_CAP_REALTIME; } @@ -1341,32 +1371,32 @@ static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res) return res; } -static int snd_pcm_oss_get_caps(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) { int result, idx; result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; for (idx = 0; idx < 2; idx++) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; result = snd_pcm_oss_get_caps1(substream, result); } result |= 0x0001; /* revision - same as SB AWE 64 */ return result; } -static void snd_pcm_oss_simulate_fill(snd_pcm_substream_t *substream, snd_pcm_uframes_t hw_ptr) +static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t appl_ptr; appl_ptr = hw_ptr + runtime->buffer_size; appl_ptr %= runtime->boundary; runtime->control->appl_ptr = appl_ptr; } -static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger) +static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger) { - snd_pcm_runtime_t *runtime; - snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; + struct snd_pcm_runtime *runtime; + struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; int err, cmd; #ifdef OSS_DEBUG @@ -1402,7 +1432,7 @@ static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger 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; } @@ -1423,7 +1453,7 @@ static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger 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; } @@ -1431,9 +1461,9 @@ static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger return 0; } -static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; + struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; int result = 0; psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -1445,10 +1475,10 @@ static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file) return result; } -static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) { - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; snd_pcm_sframes_t delay; int err; @@ -1460,7 +1490,7 @@ static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file) 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) @@ -1468,10 +1498,10 @@ static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file) return snd_pcm_oss_bytes(substream, delay); } -static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct count_info __user * _info) +static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info) { - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; snd_pcm_sframes_t delay; int fixup; struct count_info info; @@ -1518,22 +1548,28 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str snd_pcm_oss_simulate_fill(substream, delay); info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; } else { - delay = snd_pcm_oss_bytes(substream, delay) + fixup; - info.blocks = delay / runtime->oss.period_bytes; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) + delay = snd_pcm_oss_bytes(substream, delay); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + 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; info.bytes = (runtime->oss.bytes - delay) & INT_MAX; - else + } else { + delay += fixup; + info.blocks = delay / runtime->oss.period_bytes; info.bytes = (runtime->oss.bytes + delay) & INT_MAX; + } } if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0; } -static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct audio_buf_info __user *_info) +static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info) { - snd_pcm_substream_t *substream; - snd_pcm_runtime_t *runtime; + struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; snd_pcm_sframes_t avail; int fixup; struct audio_buf_info info; @@ -1589,54 +1625,67 @@ static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, s return 0; } -static int snd_pcm_oss_get_mapbuf(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct buffmem_desc __user * _info) +static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) { // it won't be probably implemented // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n"); return -EINVAL; } -static snd_pcm_oss_setup_t *snd_pcm_oss_look_for_setup(snd_pcm_t *pcm, int stream, const char *task_name) +static const char *strip_task_path(const char *path) { - const char *ptr, *ptrl; - snd_pcm_oss_setup_t *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_init_substream(snd_pcm_substream_t *substream, - snd_pcm_oss_setup_t *setup, +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_oss_setup *setup, int minor) { - snd_pcm_runtime_t *runtime; + 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; @@ -1655,139 +1704,69 @@ static void snd_pcm_oss_init_substream(snd_pcm_substream_t *substream, runtime->oss.fragshift = 0; runtime->oss.maxfrags = 0; runtime->oss.subdivision = 0; + substream->pcm_release = snd_pcm_oss_release_substream; } -static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream) -{ - snd_pcm_runtime_t *runtime; - runtime = substream->runtime; - if (runtime->oss.buffer) - vfree(runtime->oss.buffer); - snd_pcm_oss_plugin_clear(substream); - substream->oss.file = NULL; - substream->oss.oss = 0; -} - -static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file) +static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) { int cidx; snd_assert(pcm_oss_file != NULL, return -ENXIO); for (cidx = 0; cidx < 2; ++cidx) { - snd_pcm_substream_t *substream = pcm_oss_file->streams[cidx]; - snd_pcm_runtime_t *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->open_flag) { - if (substream->ops->hw_free != NULL) - substream->ops->hw_free(substream); - substream->ops->close(substream); - substream->open_flag = 0; - } - substream->ffile = NULL; - snd_pcm_oss_release_substream(substream); - snd_pcm_release_substream(substream); + struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; + if (substream) + snd_pcm_release_substream(substream); } - snd_magic_kfree(pcm_oss_file); + kfree(pcm_oss_file); return 0; } static int snd_pcm_oss_open_file(struct file *file, - snd_pcm_t *pcm, - snd_pcm_oss_file_t **rpcm_oss_file, + struct snd_pcm *pcm, + struct snd_pcm_oss_file **rpcm_oss_file, int minor, - snd_pcm_oss_setup_t *psetup, - snd_pcm_oss_setup_t *csetup) + struct snd_pcm_oss_setup *setup) { - int err = 0; - snd_pcm_oss_file_t *pcm_oss_file; - snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; + int idx, err; + struct snd_pcm_oss_file *pcm_oss_file; + struct snd_pcm_substream *substream; unsigned int f_mode = file->f_mode; snd_assert(rpcm_oss_file != NULL, return -EINVAL); *rpcm_oss_file = NULL; - pcm_oss_file = snd_magic_kcalloc(snd_pcm_oss_file_t, 0, GFP_KERNEL); + pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); if (pcm_oss_file == NULL) return -ENOMEM; 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->open_flag = 1; - 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; - } - psubstream->ffile = file; - 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->open_flag = 1; - 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; - } - csubstream->ffile = file; - snd_pcm_oss_init_substream(csubstream, csetup, minor); - } file->private_data = pcm_oss_file; *rpcm_oss_file = pcm_oss_file; @@ -1795,24 +1774,36 @@ static int snd_pcm_oss_open_file(struct file *file, } +static int snd_task_name(struct task_struct *task, char *name, size_t size) +{ + unsigned int idx; + + snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); + for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) + name[idx] = task->comm[idx]; + name[idx] = '\0'; + return 0; +} + static int snd_pcm_oss_open(struct inode *inode, struct file *file) { - int minor = iminor(inode); - int cardnum = SNDRV_MINOR_OSS_CARD(minor); - int device; int err; char task_name[32]; - snd_pcm_t *pcm; - snd_pcm_oss_file_t *pcm_oss_file; - snd_pcm_oss_setup_t *psetup = NULL, *csetup = NULL; + struct snd_pcm *pcm; + struct snd_pcm_oss_file *pcm_oss_file; + struct snd_pcm_oss_setup setup[2]; int nonblock; wait_queue_t wait; + static char printed_comm[16]; - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); - device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ? - adsp_map[cardnum] : dsp_map[cardnum]; + if (strncmp(printed_comm, current->comm, 16)) { + printk(KERN_DEBUG "application %s uses obsolete OSS audio interface\n", + current->comm); + memcpy(printed_comm, current->comm, 16); + } - pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device]; + pcm = snd_lookup_oss_minor_data(iminor(inode), + SNDRV_OSS_DEVICE_TYPE_PCM); if (pcm == NULL) { err = -ENODEV; goto __error1; @@ -1828,32 +1819,24 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) 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, - minor, psetup, csetup); + iminor(inode), setup); if (err >= 0) break; if (err == -EAGAIN) { @@ -1864,16 +1847,16 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) } 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; @@ -1888,41 +1871,40 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) static int snd_pcm_oss_release(struct inode *inode, struct file *file) { - snd_pcm_t *pcm; - snd_pcm_substream_t *substream; - snd_pcm_oss_file_t *pcm_oss_file; + struct snd_pcm *pcm; + struct snd_pcm_substream *substream; + struct snd_pcm_oss_file *pcm_oss_file; - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); + pcm_oss_file = file->private_data; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 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); return 0; } -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - snd_pcm_oss_file_t *pcm_oss_file; + struct snd_pcm_oss_file *pcm_oss_file; int __user *p = (int __user *)arg; int res; - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); + pcm_oss_file = file->private_data; if (cmd == OSS_GETVERSION) return put_user(SNDRV_OSS_VERSION, p); if (cmd == OSS_ALSAEMULVER) return put_user(1, p); #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE)) if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ - snd_pcm_substream_t *substream; + struct snd_pcm_substream *substream; int idx; for (idx = 0; idx < 2; ++idx) { substream = pcm_oss_file->streams[idx]; @@ -2068,12 +2050,19 @@ static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, return -EINVAL; } +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl +#else +#define snd_pcm_oss_ioctl_compat NULL +#endif + static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { - snd_pcm_oss_file_t *pcm_oss_file; - snd_pcm_substream_t *substream; + struct snd_pcm_oss_file *pcm_oss_file; + struct snd_pcm_substream *substream; - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); + pcm_oss_file = file->private_data; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (substream == NULL) return -ENXIO; @@ -2090,35 +2079,33 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { - snd_pcm_oss_file_t *pcm_oss_file; - snd_pcm_substream_t *substream; + struct snd_pcm_oss_file *pcm_oss_file; + struct snd_pcm_substream *substream; long result; - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); + pcm_oss_file = file->private_data; 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 return result; } -static int snd_pcm_oss_playback_ready(snd_pcm_substream_t *substream) +static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&runtime->mmap_count)) return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; else return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; } -static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream) +static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) { - snd_pcm_runtime_t *runtime = substream->runtime; + struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&runtime->mmap_count)) return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; else @@ -2127,18 +2114,18 @@ static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream) static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) { - snd_pcm_oss_file_t *pcm_oss_file; + struct snd_pcm_oss_file *pcm_oss_file; unsigned int mask; - snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; + struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return 0); + pcm_oss_file = file->private_data; psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; mask = 0; if (psubstream != NULL) { - snd_pcm_runtime_t *runtime = psubstream->runtime; + struct snd_pcm_runtime *runtime = psubstream->runtime; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(psubstream); if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && @@ -2148,8 +2135,8 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) snd_pcm_stream_unlock_irq(psubstream); } if (csubstream != NULL) { - snd_pcm_runtime_t *runtime = csubstream->runtime; - enum sndrv_pcm_state ostate; + struct snd_pcm_runtime *runtime = csubstream->runtime; + snd_pcm_state_t ostate; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(csubstream); if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || @@ -2157,7 +2144,7 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) mask |= POLLIN | POLLRDNORM; snd_pcm_stream_unlock_irq(csubstream); if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { - snd_pcm_oss_file_t ofile; + struct snd_pcm_oss_file ofile; memset(&ofile, 0, sizeof(ofile)); ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; runtime->oss.trigger = 0; @@ -2170,15 +2157,15 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) { - snd_pcm_oss_file_t *pcm_oss_file; - snd_pcm_substream_t *substream = NULL; - snd_pcm_runtime_t *runtime; + struct snd_pcm_oss_file *pcm_oss_file; + struct snd_pcm_substream *substream = NULL; + struct snd_pcm_runtime *runtime; int err; #ifdef OSS_DEBUG printk("pcm_oss: mmap begin\n"); #endif - pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); + pcm_oss_file = file->private_data; switch ((area->vm_flags & (VM_READ | VM_WRITE))) { case VM_READ | VM_WRITE: substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -2211,8 +2198,10 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) 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; @@ -2232,16 +2221,17 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) return 0; } +#ifdef CONFIG_SND_VERBOSE_PROCFS /* * /proc interface */ -static void snd_pcm_oss_proc_read(snd_info_entry_t *entry, - snd_info_buffer_t * buffer) +static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) { - snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data; - snd_pcm_oss_setup_t *setup = pstr->oss.setup_list; - down(&pstr->oss.setup_mutex); + struct snd_pcm_str *pstr = entry->private_data; + struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; + mutex_lock(&pstr->oss.setup_mutex); while (setup) { snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", setup->task_name, @@ -2255,18 +2245,13 @@ static void snd_pcm_oss_proc_read(snd_info_entry_t *entry, 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(snd_pcm_str_t * pstr) +static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) { - unsigned int idx; - snd_pcm_substream_t *substream; - snd_pcm_oss_setup_t *setup, *setupn; + 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; @@ -2276,21 +2261,21 @@ static void snd_pcm_oss_proc_free_setup_list(snd_pcm_str_t * pstr) pstr->oss.setup_list = NULL; } -static void snd_pcm_oss_proc_write(snd_info_entry_t *entry, - snd_info_buffer_t * buffer) +static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) { - snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data; - char line[512], str[32], task_name[32], *ptr; + struct snd_pcm_str *pstr = entry->private_data; + char line[128], str[32], task_name[32], *ptr; int idx1; - snd_pcm_oss_setup_t *setup, *setup1, template; + 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) { @@ -2322,34 +2307,43 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry, template.partialfrag = 1; } else if (!strcmp(str, "no-silence")) { template.nosilence = 1; + } else if (!strcmp(str, "buggy-ptr")) { + template.buggyptr = 1; } } while (*str); if (setup == NULL) { - setup = (snd_pcm_oss_setup_t *) kmalloc(sizeof(snd_pcm_oss_setup_t), 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 = snd_kmalloc_strdup(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); } } -static void snd_pcm_oss_proc_init(snd_pcm_t *pcm) +static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) { int stream; for (stream = 0; stream < 2; ++stream) { - snd_info_entry_t *entry; - snd_pcm_str_t *pstr = &pcm->streams[stream]; + struct snd_info_entry *entry; + struct snd_pcm_str *pstr = &pcm->streams[stream]; if (pstr->substream_count == 0) continue; if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { @@ -2369,11 +2363,11 @@ static void snd_pcm_oss_proc_init(snd_pcm_t *pcm) } } -static void snd_pcm_oss_proc_done(snd_pcm_t *pcm) +static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) { int stream; for (stream = 0; stream < 2; ++stream) { - snd_pcm_str_t *pstr = &pcm->streams[stream]; + struct snd_pcm_str *pstr = &pcm->streams[stream]; if (pstr->oss.proc_entry) { snd_info_unregister(pstr->oss.proc_entry); pstr->oss.proc_entry = NULL; @@ -2381,6 +2375,10 @@ static void snd_pcm_oss_proc_done(snd_pcm_t *pcm) } } } +#else /* !CONFIG_SND_VERBOSE_PROCFS */ +#define snd_pcm_oss_proc_init(pcm) +#define snd_pcm_oss_proc_done(pcm) +#endif /* CONFIG_SND_VERBOSE_PROCFS */ /* * ENTRY functions @@ -2394,28 +2392,24 @@ static struct file_operations snd_pcm_oss_f_reg = .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, .poll = snd_pcm_oss_poll, - .ioctl = snd_pcm_oss_ioctl, + .unlocked_ioctl = snd_pcm_oss_ioctl, + .compat_ioctl = snd_pcm_oss_ioctl_compat, .mmap = snd_pcm_oss_mmap, }; -static snd_minor_t snd_pcm_oss_reg = -{ - .comment = "digital audio", - .f_ops = &snd_pcm_oss_f_reg, -}; - -static void register_oss_dsp(snd_pcm_t *pcm, int index) +static void register_oss_dsp(struct snd_pcm *pcm, int index) { char name[128]; sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, - pcm->card, index, &snd_pcm_oss_reg, - name) < 0) { - snd_printk("unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device); + pcm->card, index, &snd_pcm_oss_f_reg, + pcm, name) < 0) { + snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", + pcm->card->number, pcm->device); } } -static int snd_pcm_oss_register_minor(snd_pcm_t * pcm) +static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) { pcm->oss.reg = 0; if (dsp_map[pcm->card->number] == (int)pcm->device) { @@ -2446,7 +2440,7 @@ static int snd_pcm_oss_register_minor(snd_pcm_t * pcm) return 0; } -static int snd_pcm_oss_disconnect_minor(snd_pcm_t * pcm) +static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) { if (pcm->oss.reg) { if (pcm->oss.reg_mask & 1) { @@ -2463,7 +2457,7 @@ static int snd_pcm_oss_disconnect_minor(snd_pcm_t * pcm) return 0; } -static int snd_pcm_oss_unregister_minor(snd_pcm_t * pcm) +static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) { snd_pcm_oss_disconnect_minor(pcm); if (pcm->oss.reg) { @@ -2478,7 +2472,7 @@ static int snd_pcm_oss_unregister_minor(snd_pcm_t * pcm) return 0; } -static snd_pcm_notify_t snd_pcm_oss_notify = +static struct snd_pcm_notify snd_pcm_oss_notify = { .n_register = snd_pcm_oss_register_minor, .n_disconnect = snd_pcm_oss_disconnect_minor, @@ -2493,11 +2487,13 @@ static int __init alsa_pcm_oss_init(void) /* check device map table */ for (i = 0; i < SNDRV_CARDS; i++) { if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk("invalid dsp_map[%d] = %d\n", i, dsp_map[i]); + snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", + i, dsp_map[i]); dsp_map[i] = 0; } if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk("invalid adsp_map[%d] = %d\n", i, adsp_map[i]); + snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", + i, adsp_map[i]); adsp_map[i] = 1; } }