diff options
Diffstat (limited to 'sound/core/oss/pcm_oss.c')
| -rw-r--r-- | sound/core/oss/pcm_oss.c | 292 |
1 files changed, 180 insertions, 112 deletions
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 4c601b192dd..ada69d7a8d7 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -30,7 +30,8 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/vmalloc.h> -#include <linux/moduleparam.h> +#include <linux/module.h> +#include <linux/math64.h> #include <linux/string.h> #include <sound/core.h> #include <sound/minors.h> @@ -40,12 +41,13 @@ #include <sound/info.h> #include <linux/soundcard.h> #include <sound/initval.h> +#include <sound/mixer_oss.h> #define OSS_ALSAEMULVER _SIOR ('M', 249, int) static int dsp_map[SNDRV_CARDS]; static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static int nonblock_open = 1; +static bool nonblock_open = 1; MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); @@ -59,7 +61,6 @@ MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); -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); @@ -452,7 +453,10 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, } else { *params = *save; max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); - snd_assert(max >= 0, return -EINVAL); + if (max < 0) { + kfree(save); + return max; + } last = 1; } _end: @@ -461,7 +465,7 @@ static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, v = snd_pcm_hw_param_last(pcm, params, var, dir); else v = snd_pcm_hw_param_first(pcm, params, var, dir); - snd_assert(v >= 0, return -EINVAL); + snd_BUG_ON(v < 0); return v; } @@ -616,9 +620,7 @@ static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) #else { u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; - u32 rem; - div64_32(&bsize, buffer_size, &rem); - return (long)bsize; + return div_u64(bsize, buffer_size); } #endif } @@ -632,6 +634,12 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); } +static inline +snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime) +{ + return runtime->hw_ptr_interrupt; +} + /* define extended formats in the recent OSS versions (if any) */ /* linear formats */ #define AFMT_S32_LE 0x00001000 @@ -648,7 +656,7 @@ static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) #define AFMT_AC3 0x00000400 #define AFMT_VORBIS 0x00000800 -static int snd_pcm_oss_format_from(int format) +static snd_pcm_format_t snd_pcm_oss_format_from(int format) { switch (format) { case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; @@ -672,7 +680,7 @@ static int snd_pcm_oss_format_from(int format) } } -static int snd_pcm_oss_format_to(int format) +static int snd_pcm_oss_format_to(snd_pcm_format_t format) { switch (format) { case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; @@ -778,7 +786,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, while (oss_period_size * oss_periods > oss_buffer_size) oss_period_size /= 2; - snd_assert(oss_period_size >= 16, return -EINVAL); + if (oss_period_size < 16) + return -EINVAL; runtime->oss.period_bytes = oss_period_size; runtime->oss.period_frames = 1; runtime->oss.periods = oss_periods; @@ -834,7 +843,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) size_t oss_frame_size; int err; int direct; - int format, sformat, n; + snd_pcm_format_t format, sformat; + int n; struct snd_mask sformat_mask; struct snd_mask mask; @@ -844,7 +854,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) params = kmalloc(sizeof(*params), GFP_KERNEL); sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); if (!sw_params || !params || !sparams) { - snd_printd("No memory\n"); + pcm_dbg(substream->pcm, "No memory\n"); err = -ENOMEM; goto failure; } @@ -859,15 +869,15 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); snd_mask_none(&mask); if (atomic_read(&substream->mmap_count)) - snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); + snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); else { - snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); + snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED); if (!direct) - snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); + snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); } err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); if (err < 0) { - snd_printd("No usable accesses\n"); + pcm_dbg(substream->pcm, "No usable accesses\n"); err = -EINVAL; goto failure; } @@ -882,29 +892,33 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) else sformat = snd_pcm_plug_slave_format(format, &sformat_mask); - if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) { - for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) { - if (snd_mask_test(&sformat_mask, sformat) && + if ((__force int)sformat < 0 || + !snd_mask_test(&sformat_mask, (__force int)sformat)) { + for (sformat = (__force snd_pcm_format_t)0; + (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; + sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { + if (snd_mask_test(&sformat_mask, (__force int)sformat) && snd_pcm_oss_format_to(sformat) >= 0) break; } - if (sformat > SNDRV_PCM_FORMAT_LAST) { - snd_printd("Cannot find a format!!!\n"); + if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { + pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); err = -EINVAL; goto failure; } } - err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0); - snd_assert(err >= 0, goto failure); + err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); + if (err < 0) + goto failure; if (direct) { memcpy(params, sparams, sizeof(*params)); } else { _snd_pcm_hw_params_any(params); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, - SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); + (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, - snd_pcm_oss_format_from(runtime->oss.format), 0); + (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, 0); _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, @@ -928,14 +942,16 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) if ((err = snd_pcm_plug_format_plugins(substream, params, sparams)) < 0) { - snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err); + pcm_dbg(substream->pcm, + "snd_pcm_plug_format_plugins failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); goto failure; } if (runtime->oss.plugin_first) { 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); + pcm_dbg(substream->pcm, + "snd_pcm_plugin_build_io failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); goto failure; } @@ -958,16 +974,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size); err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL); - snd_assert(err >= 0, goto failure); + if (err < 0) + goto failure; err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS, runtime->oss.periods, NULL); - snd_assert(err >= 0, goto failure); + if (err < 0) + goto failure; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) { - snd_printd("HW_PARAMS failed: %i\n", err); + pcm_dbg(substream->pcm, "HW_PARAMS failed: %i\n", err); goto failure; } @@ -1000,13 +1018,16 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) } if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { - snd_printd("SW_PARAMS failed: %i\n", err); + pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); goto failure; } 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); + if (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); @@ -1017,7 +1038,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) oss_period_size *= oss_frame_size; oss_buffer_size = oss_period_size * runtime->oss.periods; - snd_assert(oss_buffer_size >= 0, err = -EINVAL; goto failure); + if (oss_buffer_size < 0) { + err = -EINVAL; + goto failure; + } runtime->oss.period_bytes = oss_period_size; runtime->oss.buffer_bytes = oss_buffer_size; @@ -1033,10 +1057,15 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) runtime->oss.channels = params_channels(params); runtime->oss.rate = params_rate(params); - runtime->oss.params = 0; - runtime->oss.prepare = 1; vfree(runtime->oss.buffer); runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); + if (!runtime->oss.buffer) { + err = -ENOMEM; + goto failure; + } + + runtime->oss.params = 0; + runtime->oss.prepare = 1; runtime->oss.buffer_used = 0; if (runtime->dma_area) snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); @@ -1069,7 +1098,8 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil return err; } } - snd_assert(asubstream != NULL, return -EIO); + if (!asubstream) + return -EIO; if (r_substream) *r_substream = asubstream; return 0; @@ -1082,11 +1112,12 @@ static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); if (err < 0) { - snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); + pcm_dbg(substream->pcm, + "snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); return err; } runtime->oss.prepare = 0; - runtime->oss.prev_hw_ptr_interrupt = 0; + runtime->oss.prev_hw_ptr_period = 0; runtime->oss.period_ptr = 0; runtime->oss.buffer_used = 0; @@ -1147,10 +1178,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: write: recovering from XRUN\n"); - else - printk("pcm_oss: write: recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: write: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1159,10 +1190,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); + ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); + ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); } if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -1183,10 +1214,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: read: recovering from XRUN\n"); - else - printk("pcm_oss: read: recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: read: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1202,10 +1233,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); + ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); snd_leave_user(fs); } else { - ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); + ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); } if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { @@ -1229,10 +1260,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: writev: recovering from XRUN\n"); - else - printk("pcm_oss: writev: recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: writev: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) @@ -1265,10 +1296,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk("pcm_oss: readv: recovering from XRUN\n"); - else - printk("pcm_oss: readv: recovering from SUSPEND\n"); + pcm_dbg(substream->pcm, + "pcm_oss: readv: recovering from %s\n", + runtime->status->state == SNDRV_PCM_STATE_XRUN ? + "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) @@ -1301,7 +1332,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha 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, (const char __user *)buf, bytes)) + if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes)) return -EFAULT; buf = runtime->oss.buffer; } @@ -1397,7 +1428,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, 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; + char __user *final_dst = (char __force __user *)buf; if (runtime->oss.plugin_first) { 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; @@ -1480,16 +1511,19 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) { struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + int i; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream != 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) { + for (i = 0; i < 2; i++) { + substream = pcm_oss_file->streams[i]; + if (!substream) + continue; + runtime = substream->runtime; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - substream->runtime->oss.prepare = 1; + runtime->oss.prepare = 1; + runtime->oss.buffer_used = 0; + runtime->oss.prev_hw_ptr_period = 0; + runtime->oss.period_ptr = 0; } return 0; } @@ -1514,6 +1548,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) { struct snd_pcm_runtime *runtime; ssize_t result = 0; + snd_pcm_state_t state; long res; wait_queue_t wait; @@ -1521,7 +1556,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); #ifdef OSS_DEBUG - printk("sync1: size = %li\n", size); + pcm_dbg(substream->pcm, "sync1: size = %li\n", size); #endif while (1) { result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); @@ -1535,9 +1570,9 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) result = 0; set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_lock_irq(substream); - res = runtime->status->state; + state = runtime->status->state; snd_pcm_stream_unlock_irq(substream); - if (res != SNDRV_PCM_STATE_RUNNING) { + if (state != SNDRV_PCM_STATE_RUNNING) { set_current_state(TASK_RUNNING); break; } @@ -1547,7 +1582,8 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) break; } if (res == 0) { - snd_printk(KERN_ERR "OSS sync error - DMA timeout\n"); + pcm_err(substream->pcm, + "OSS sync error - DMA timeout\n"); result = -EIO; break; } @@ -1578,7 +1614,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) mutex_lock(&runtime->oss.params_lock); if (runtime->oss.buffer_used > 0) { #ifdef OSS_DEBUG - printk("sync: buffer_used\n"); + pcm_dbg(substream->pcm, "sync: buffer_used\n"); #endif size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; snd_pcm_format_set_silence(format, @@ -1591,7 +1627,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) } } else if (runtime->oss.period_ptr > 0) { #ifdef OSS_DEBUG - printk("sync: period_ptr\n"); + pcm_dbg(substream->pcm, "sync: period_ptr\n"); #endif size = runtime->oss.period_bytes - runtime->oss.period_ptr; snd_pcm_format_set_silence(format, @@ -1623,7 +1659,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) size1); size1 /= runtime->channels; /* frames */ fs = snd_enter_user(); - snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); + snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1); snd_leave_user(fs); } } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { @@ -1755,7 +1791,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | AFMT_S32_LE | AFMT_S32_BE | - AFMT_S24_LE | AFMT_S24_LE | + AFMT_S24_LE | AFMT_S24_BE | AFMT_S24_PACKED; params = kmalloc(sizeof(*params), GFP_KERNEL); if (!params) @@ -1764,7 +1800,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) 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); + if (err < 0) + return err; for (fmt = 0; fmt < 32; ++fmt) { if (snd_mask_test(&format_mask, fmt)) { int f = snd_pcm_oss_format_to(fmt); @@ -1882,7 +1919,9 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig static int snd_pcm_oss_nonblock(struct file * file) { + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; } @@ -1923,7 +1962,8 @@ static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) return result; } -static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *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) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t appl_ptr; @@ -1939,7 +1979,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr int err, cmd; #ifdef OSS_DEBUG - printk("pcm_oss: trigger = 0x%x\n", trigger); + pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); #endif psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; @@ -1959,7 +1999,8 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr if (runtime->oss.trigger) goto _skip1; if (atomic_read(&psubstream->mmap_count)) - snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); + snd_pcm_oss_simulate_fill(psubstream, + get_hw_ptr_period(runtime)); runtime->oss.trigger = 1; runtime->start_threshold = 1; cmd = SNDRV_PCM_IOCTL_START; @@ -2078,11 +2119,12 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); if (atomic_read(&substream->mmap_count)) { snd_pcm_sframes_t n; - n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; + delay = get_hw_ptr_period(runtime); + n = delay - runtime->oss.prev_hw_ptr_period; if (n < 0) n += runtime->boundary; info.blocks = n / runtime->period_size; - runtime->oss.prev_hw_ptr_interrupt = delay; + runtime->oss.prev_hw_ptr_period = delay; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_pcm_oss_simulate_fill(substream, delay); info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; @@ -2157,7 +2199,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre } #ifdef OSS_DEBUG - printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); + pcm_dbg(substream->pcm, + "pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", + info.bytes, info.fragments, info.fragstotal, info.fragsize); #endif if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -2167,7 +2211,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre 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"); + // pr_debug("TODO: snd_pcm_oss_get_mapbuf\n"); return -EINVAL; } @@ -2250,7 +2294,8 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 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); + if (!pcm_oss_file) + return 0; for (cidx = 0; cidx < 2; ++cidx) { struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; if (substream) @@ -2269,10 +2314,10 @@ static int snd_pcm_oss_open_file(struct file *file, int idx, err; struct snd_pcm_oss_file *pcm_oss_file; struct snd_pcm_substream *substream; - unsigned int f_mode = file->f_mode; + fmode_t f_mode = file->f_mode; - snd_assert(rpcm_oss_file != NULL, return -EINVAL); - *rpcm_oss_file = NULL; + if (rpcm_oss_file) + *rpcm_oss_file = NULL; pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); if (pcm_oss_file == NULL) @@ -2312,7 +2357,8 @@ static int snd_pcm_oss_open_file(struct file *file, } file->private_data = pcm_oss_file; - *rpcm_oss_file = pcm_oss_file; + if (rpcm_oss_file) + *rpcm_oss_file = pcm_oss_file; return 0; } @@ -2321,7 +2367,8 @@ 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); + if (snd_BUG_ON(!task || !name || size < 2)) + return -EINVAL; for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) name[idx] = task->comm[idx]; name[idx] = '\0'; @@ -2338,6 +2385,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) int nonblock; wait_queue_t wait; + err = nonseekable_open(inode, file); + if (err < 0) + return err; + pcm = snd_lookup_oss_minor_data(iminor(inode), SNDRV_OSS_DEVICE_TYPE_PCM); if (pcm == NULL) { @@ -2386,6 +2437,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -2395,6 +2450,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; + snd_card_unref(pcm->card); return err; __error: @@ -2402,6 +2458,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: + if (pcm) + snd_card_unref(pcm->card); return err; } @@ -2415,7 +2473,8 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) 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); + if (snd_BUG_ON(!substream)) + return -ENXIO; pcm = substream->pcm; if (!pcm->card->shutdown) snd_pcm_oss_sync(pcm_oss_file); @@ -2448,14 +2507,15 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (substream != NULL) break; } - snd_assert(substream != NULL, return -ENXIO); + if (snd_BUG_ON(idx >= 2)) + return -ENXIO; return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); } #endif if (((cmd >> 8) & 0xff) != 'P') return -EINVAL; #ifdef OSS_DEBUG - printk("pcm_oss: ioctl = 0x%x\n", cmd); + pr_debug("pcm_oss: ioctl = 0x%x\n", cmd); #endif switch (cmd) { case SNDCTL_DSP_RESET: @@ -2582,7 +2642,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDCTL_DSP_PROFILE: return 0; /* silently ignore */ default: - snd_printd("pcm_oss: unknown command = 0x%x\n", cmd); + pr_debug("pcm_oss: unknown command = 0x%x\n", cmd); } return -EINVAL; } @@ -2609,7 +2669,9 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun #else { ssize_t res = snd_pcm_oss_read1(substream, buf, count); - printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); + pcm_dbg(substream->pcm, + "pcm_oss: read %li bytes (returned %li bytes)\n", + (long)count, (long)res); return res; } #endif @@ -2628,7 +2690,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size substream->f_flags = file->f_flags & O_NONBLOCK; result = snd_pcm_oss_write1(substream, buf, count); #ifdef OSS_DEBUG - printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); + pcm_dbg(substream->pcm, "pcm_oss: write %li bytes (wrote %li bytes)\n", + (long)count, (long)result); #endif return result; } @@ -2637,18 +2700,22 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&substream->mmap_count)) - return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; + return runtime->oss.prev_hw_ptr_period != + get_hw_ptr_period(runtime); else - return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; + return snd_pcm_playback_avail(runtime) >= + runtime->oss.period_frames; } static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; if (atomic_read(&substream->mmap_count)) - return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; + return runtime->oss.prev_hw_ptr_period != + get_hw_ptr_period(runtime); else - return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; + return snd_pcm_capture_avail(runtime) >= + runtime->oss.period_frames; } static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) @@ -2702,7 +2769,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) int err; #ifdef OSS_DEBUG - printk("pcm_oss: mmap begin\n"); + pr_debug("pcm_oss: mmap begin\n"); #endif pcm_oss_file = file->private_data; switch ((area->vm_flags & (VM_READ | VM_WRITE))) { @@ -2752,7 +2819,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) runtime->silence_threshold = 0; runtime->silence_size = 0; #ifdef OSS_DEBUG - printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); + pr_debug("pcm_oss: mmap ok, bytes = 0x%x\n", + runtime->oss.mmap_bytes); #endif /* In mmap mode we never stop */ runtime->stop_threshold = runtime->boundary; @@ -2804,7 +2872,8 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_pcm_str *pstr = entry->private_data; - char line[128], str[32], task_name[32], *ptr; + char line[128], str[32], task_name[32]; + const char *ptr; int idx1; struct snd_pcm_oss_setup *setup, *setup1, template; @@ -2854,7 +2923,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, setup = kmalloc(sizeof(*setup), GFP_KERNEL); if (! setup) { buffer->error = -ENOMEM; - mutex_lock(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); return; } if (pstr->oss.setup_list == NULL) @@ -2868,7 +2937,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, if (! template.task_name) { kfree(setup); buffer->error = -ENOMEM; - mutex_lock(&pstr->oss.setup_mutex); + mutex_unlock(&pstr->oss.setup_mutex); return; } } @@ -2926,6 +2995,7 @@ static const struct file_operations snd_pcm_oss_f_reg = .write = snd_pcm_oss_write, .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, + .llseek = no_llseek, .poll = snd_pcm_oss_poll, .unlocked_ioctl = snd_pcm_oss_ioctl, .compat_ioctl = snd_pcm_oss_ioctl_compat, @@ -2934,12 +3004,10 @@ static const struct file_operations snd_pcm_oss_f_reg = 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_f_reg, - pcm, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", + pcm) < 0) { + pcm_err(pcm, "unable to register OSS PCM device %i:%i\n", pcm->card->number, pcm->device); } } @@ -3020,12 +3088,12 @@ 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(KERN_ERR "invalid dsp_map[%d] = %d\n", + pr_err("ALSA: pcm_oss: 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(KERN_ERR "invalid adsp_map[%d] = %d\n", + pr_err("ALSA: pcm_oss: invalid adsp_map[%d] = %d\n", i, adsp_map[i]); adsp_map[i] = 1; } |
