X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Foss%2Fpcm_oss.c;h=cc76a98d4c20231d726c111fb3cccd0b319e925d;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;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..cc76a98d4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -45,21 +46,17 @@ 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); @@ -80,7 +77,7 @@ static inline void snd_leave_user(mm_segment_t fs) set_fs(fs); } -int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) +static int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_plugin_t *plugin, *next; @@ -95,7 +92,7 @@ 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(snd_pcm_plugin_t *plugin) { snd_pcm_runtime_t *runtime = plugin->plug->runtime; plugin->next = runtime->oss.plugin_first; @@ -516,8 +513,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,12 +523,9 @@ 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; } @@ -832,13 +825,18 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u xfer += tmp; if ((substream->oss.setup != NULL && 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); @@ -848,6 +846,9 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u buf += tmp; bytes -= tmp; xfer += tmp; + if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && + tmp != runtime->oss.period_bytes) + break; } } return xfer; @@ -1177,10 +1178,11 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) snd_pcm_substream_t *substream; int err; int direct; - snd_pcm_hw_params_t params; + snd_pcm_hw_params_t *params; unsigned int formats = 0; snd_mask_t 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)) { @@ -1194,10 +1196,14 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file) 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); @@ -1661,8 +1667,7 @@ 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); + vfree(runtime->oss.buffer); snd_pcm_oss_plugin_clear(substream); substream->oss.file = NULL; substream->oss.oss = 0; @@ -1693,7 +1698,7 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file) snd_pcm_oss_release_substream(substream); snd_pcm_release_substream(substream); } - snd_magic_kfree(pcm_oss_file); + kfree(pcm_oss_file); return 0; } @@ -1712,7 +1717,7 @@ static int snd_pcm_oss_open_file(struct file *file, 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 = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL); if (pcm_oss_file == NULL) return -ENOMEM; @@ -1892,7 +1897,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) snd_pcm_substream_t *substream; snd_pcm_oss_file_t *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]; @@ -1908,14 +1913,14 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) return 0; } -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { snd_pcm_oss_file_t *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) @@ -2068,12 +2073,23 @@ static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, return -EINVAL; } +/* FIXME: need to unlock BKL to allow preemption */ +static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int err; + unlock_kernel(); + err = _snd_pcm_oss_ioctl(inode, file, cmd, arg); + lock_kernel(); + return err; +} + 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; - 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; @@ -2094,7 +2110,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size snd_pcm_substream_t *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; @@ -2131,7 +2147,7 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) unsigned int mask; snd_pcm_substream_t *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]; @@ -2178,7 +2194,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) #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]; @@ -2280,7 +2296,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data; - char line[512], str[32], task_name[32], *ptr; + char line[256], str[32], task_name[32], *ptr; int idx1; snd_pcm_oss_setup_t *setup, *setup1, template;