diff options
Diffstat (limited to '')
-rw-r--r-- | sound/core/oss/mixer_oss.c | 99 | ||||
-rw-r--r-- | sound/core/oss/mulaw.c | 4 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 246 | ||||
-rw-r--r-- | sound/core/oss/pcm_plugin.c | 161 | ||||
-rw-r--r-- | sound/core/oss/pcm_plugin.h | 2 | ||||
-rw-r--r-- | sound/core/oss/rate.c | 6 |
6 files changed, 307 insertions, 211 deletions
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index f702c96a7478..9620115cfdc0 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -87,8 +87,8 @@ static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer, struct mixer_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); + strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); + strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); info.modify_counter = card->mixer_oss_change_count; if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -103,8 +103,8 @@ static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer, _old_mixer_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); + strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); + strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0; @@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer) if (mixer == NULL) return -EIO; + mutex_lock(&mixer->reg_mutex); for (chn = 0; chn < 31; chn++) { pslot = &mixer->slots[chn]; if (pslot->put_volume || pslot->put_recsrc) result |= 1 << chn; } + mutex_unlock(&mixer->reg_mutex); return result; } @@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer) if (mixer == NULL) return -EIO; + mutex_lock(&mixer->reg_mutex); for (chn = 0; chn < 31; chn++) { pslot = &mixer->slots[chn]; if (pslot->put_volume && pslot->stereo) result |= 1 << chn; } + mutex_unlock(&mixer->reg_mutex); return result; } @@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) if (mixer == NULL) return -EIO; + mutex_lock(&mixer->reg_mutex); if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ result = mixer->mask_recsrc; } else { @@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) result |= 1 << chn; } } + mutex_unlock(&mixer->reg_mutex); return result; } @@ -182,11 +188,12 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) if (mixer == NULL) return -EIO; + mutex_lock(&mixer->reg_mutex); if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ - int err; unsigned int index; - if ((err = mixer->get_recsrc(fmixer, &index)) < 0) - return err; + result = mixer->get_recsrc(fmixer, &index); + if (result < 0) + goto unlock; result = 1 << index; } else { struct snd_mixer_oss_slot *pslot; @@ -201,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) } } } - return mixer->oss_recsrc = result; + mixer->oss_recsrc = result; + unlock: + mutex_unlock(&mixer->reg_mutex); + return result; } static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc) @@ -214,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr if (mixer == NULL) return -EIO; + mutex_lock(&mixer->reg_mutex); if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */ if (recsrc & ~mixer->oss_recsrc) recsrc &= ~mixer->oss_recsrc; @@ -239,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr } } } + mutex_unlock(&mixer->reg_mutex); return result; } @@ -250,6 +262,7 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) if (mixer == NULL || slot > 30) return -EIO; + mutex_lock(&mixer->reg_mutex); pslot = &mixer->slots[slot]; left = pslot->volume[0]; right = pslot->volume[1]; @@ -257,15 +270,21 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) result = pslot->get_volume(fmixer, pslot, &left, &right); if (!pslot->stereo) right = left; - if (snd_BUG_ON(left < 0 || left > 100)) - return -EIO; - if (snd_BUG_ON(right < 0 || right > 100)) - return -EIO; + if (snd_BUG_ON(left < 0 || left > 100)) { + result = -EIO; + goto unlock; + } + if (snd_BUG_ON(right < 0 || right > 100)) { + result = -EIO; + goto unlock; + } if (result >= 0) { pslot->volume[0] = left; pslot->volume[1] = right; result = (left & 0xff) | ((right & 0xff) << 8); } + unlock: + mutex_unlock(&mixer->reg_mutex); return result; } @@ -278,6 +297,7 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, if (mixer == NULL || slot > 30) return -EIO; + mutex_lock(&mixer->reg_mutex); pslot = &mixer->slots[slot]; if (left > 100) left = 100; @@ -288,10 +308,13 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, if (pslot->put_volume) result = pslot->put_volume(fmixer, pslot, left, right); if (result < 0) - return result; + goto unlock; pslot->volume[0] = left; pslot->volume[1] = right; - return (left & 0xff) | ((right & 0xff) << 8); + result = (left & 0xff) | ((right & 0xff) << 8); + unlock: + mutex_unlock(&mixer->reg_mutex); + return result; } static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg) @@ -418,7 +441,7 @@ static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long n if (orange == 0) return 0; - return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin; + return DIV_ROUND_CLOSEST(nrange * (val - omin), orange) + nmin; } /* convert from alsa native to oss values (0-100) */ @@ -499,7 +522,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(id.name, name, sizeof(id.name)); + strscpy(id.name, name, sizeof(id.name)); id.index = index; return snd_ctl_find_id(card, &id); } @@ -517,7 +540,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -555,7 +579,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -620,7 +645,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -636,7 +662,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); if (uinfo->count > 1) uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); - if ((res = kctl->put(kctl, uctl)) < 0) + res = kctl->put(kctl, uctl); + if (res < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); @@ -661,7 +688,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -681,7 +709,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, } else { uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } - if ((res = kctl->put(kctl, uctl)) < 0) + res = kctl->put(kctl, uctl); + if (res < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); @@ -809,9 +838,11 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = -ENOENT; goto __unlock; } - if ((err = kctl->info(kctl, uinfo)) < 0) + err = kctl->info(kctl, uinfo); + if (err < 0) goto __unlock; - if ((err = kctl->get(kctl, uctl)) < 0) + err = kctl->get(kctl, uctl); + if (err < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) @@ -860,7 +891,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = -ENOENT; goto __unlock; } - if ((err = kctl->info(kctl, uinfo)) < 0) + err = kctl->info(kctl, uinfo); + if (err < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) @@ -915,7 +947,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl up_read(&card->controls_rwsem); return -ENOMEM; } - if ((err = kcontrol->info(kcontrol, info)) < 0) { + err = kcontrol->info(kcontrol, info); + if (err < 0) { up_read(&card->controls_rwsem); kfree(info); return err; @@ -1036,7 +1069,10 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, if (snd_mixer_oss_build_test_all(mixer, ptr, &slot)) return 0; down_read(&mixer->card->controls_rwsem); - if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { + kctl = NULL; + if (!ptr->index) + kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); + if (kctl) { struct snd_ctl_elem_info *uinfo; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -1343,9 +1379,10 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) if (mixer == NULL) return -ENOMEM; mutex_init(&mixer->reg_mutex); - if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, - card, 0, - &snd_mixer_oss_f_ops, card)) < 0) { + err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, + card, 0, + &snd_mixer_oss_f_ops, card); + if (err < 0) { dev_err(card->dev, "unable to register OSS mixer device %i:%i\n", card->number, 0); @@ -1355,7 +1392,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) mixer->oss_dev_alloc = 1; mixer->card = card; if (*card->mixername) - strlcpy(mixer->name, card->mixername, sizeof(mixer->name)); + strscpy(mixer->name, card->mixername, sizeof(mixer->name)); else snprintf(mixer->name, sizeof(mixer->name), "mixer%i", card->number); diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index 3788906421a7..fe27034f2846 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c @@ -329,8 +329,8 @@ int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, snd_BUG(); return -EINVAL; } - if (snd_BUG_ON(!snd_pcm_format_linear(format->format))) - return -ENXIO; + if (!snd_pcm_format_linear(format->format)) + return -EINVAL; err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion", src_format, dst_format, diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 13db77771f0f..ac2efeb63a39 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, * * Return the maximum value for field PAR. */ -static unsigned int +static int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var, int *dir) { @@ -682,17 +682,25 @@ 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; + ssize_t s; + ssize_t oss_buffer_size; + ssize_t oss_period_size, oss_periods; + ssize_t min_period_size, max_period_size; struct snd_pcm_runtime *runtime = substream->runtime; size_t oss_frame_size; oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8; + oss_buffer_size = snd_pcm_hw_param_value_max(slave_params, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + NULL); + if (oss_buffer_size <= 0) + return -EINVAL; oss_buffer_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; + oss_buffer_size * oss_frame_size); + if (oss_buffer_size <= 0) + return -EINVAL; oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); if (atomic_read(&substream->mmap_count)) { if (oss_buffer_size > runtime->oss.mmap_bytes) @@ -728,17 +736,21 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, min_period_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - min_period_size *= oss_frame_size; - min_period_size = roundup_pow_of_two(min_period_size); - if (oss_period_size < min_period_size) - oss_period_size = min_period_size; + if (min_period_size > 0) { + min_period_size *= oss_frame_size; + min_period_size = roundup_pow_of_two(min_period_size); + if (oss_period_size < min_period_size) + oss_period_size = min_period_size; + } max_period_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - max_period_size *= oss_frame_size; - max_period_size = rounddown_pow_of_two(max_period_size); - if (oss_period_size > max_period_size) - oss_period_size = max_period_size; + if (max_period_size > 0) { + max_period_size *= oss_frame_size; + max_period_size = rounddown_pow_of_two(max_period_size); + if (oss_period_size > max_period_size) + oss_period_size = max_period_size; + } oss_periods = oss_buffer_size / oss_period_size; @@ -746,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, 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) + if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags) s = runtime->oss.maxfrags; if (oss_periods > s) oss_periods = s; @@ -762,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, if (oss_period_size < 16) return -EINVAL; + + /* don't allocate too large period; 1MB period must be enough */ + if (oss_period_size > 1024 * 1024) + return -ENOMEM; + runtime->oss.period_bytes = oss_period_size; runtime->oss.period_frames = 1; runtime->oss.periods = oss_periods; @@ -825,6 +842,17 @@ static void unlock_params(struct snd_pcm_runtime *runtime) mutex_unlock(&runtime->oss.params_lock); } +static void snd_pcm_oss_release_buffers(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + kvfree(runtime->oss.buffer); + runtime->oss.buffer = NULL; +#ifdef CONFIG_SND_PCM_OSS_PLUGINS + snd_pcm_oss_plugin_clear(substream); +#endif +} + /* call with params_lock held */ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) { @@ -872,8 +900,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) err = -EINVAL; goto failure; } - choose_rate(substream, sparams, runtime->oss.rate); - snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); + + err = choose_rate(substream, sparams, runtime->oss.rate); + if (err < 0) + goto failure; + err = snd_pcm_hw_param_near(substream, sparams, + SNDRV_PCM_HW_PARAM_CHANNELS, + runtime->oss.channels, NULL); + if (err < 0) + goto failure; format = snd_pcm_oss_format_from(runtime->oss.format); @@ -884,20 +919,17 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) sformat = snd_pcm_plug_slave_format(format, sformat_mask); 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_mask_test_format(sformat_mask, sformat)) { + pcm_for_each_format(sformat) { + if (snd_mask_test_format(sformat_mask, sformat) && snd_pcm_oss_format_to(sformat) >= 0) - break; - } - if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { - pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); - err = -EINVAL; - goto failure; + goto format_found; } + pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); + err = -EINVAL; + goto failure; } + format_found: err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); if (err < 0) goto failure; @@ -951,21 +983,18 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) snd_pcm_oss_plugin_clear(substream); if (!direct) { /* add necessary plugins */ - snd_pcm_oss_plugin_clear(substream); - if ((err = snd_pcm_plug_format_plugins(substream, - params, - sparams)) < 0) { + err = snd_pcm_plug_format_plugins(substream, params, sparams); + if (err < 0) { 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) { + err = snd_pcm_plugin_build_io(substream, sparams, &plugin); + if (err < 0) { pcm_dbg(substream->pcm, "snd_pcm_plugin_build_io failed: %i\n", err); - snd_pcm_oss_plugin_clear(substream); goto failure; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -973,10 +1002,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) } else { err = snd_pcm_plugin_insert(plugin); } - if (err < 0) { - snd_pcm_oss_plugin_clear(substream); + if (err < 0) goto failure; - } } } #endif @@ -1008,7 +1035,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) sw_params->silence_size = frames; } - if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params); + if (err < 0) { pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); goto failure; } @@ -1026,10 +1054,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) goto failure; } #endif - oss_period_size *= oss_frame_size; - - oss_buffer_size = oss_period_size * runtime->oss.periods; - if (oss_buffer_size < 0) { + oss_period_size = array_size(oss_period_size, oss_frame_size); + oss_buffer_size = array_size(oss_period_size, runtime->oss.periods); + if (oss_buffer_size <= 0) { err = -EINVAL; goto failure; } @@ -1065,6 +1092,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) err = 0; failure: + if (err) + snd_pcm_oss_release_buffers(substream); kfree(sw_params); kfree(params); kfree(sparams); @@ -1208,25 +1237,27 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: write: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; } + mutex_unlock(&runtime->oss.params_lock); ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, frames, in_kernel); + mutex_lock(&runtime->oss.params_lock); if (ret != -EPIPE && ret != -ESTRPIPE) break; /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1238,18 +1269,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p snd_pcm_sframes_t delay; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: read: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1257,10 +1288,12 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p ret = snd_pcm_oss_capture_position_fixup(substream, &delay); if (ret < 0) break; + mutex_unlock(&runtime->oss.params_lock); ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, frames, in_kernel); + mutex_lock(&runtime->oss.params_lock); if (ret == -EPIPE) { - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (ret < 0) break; @@ -1279,12 +1312,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: writev: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); @@ -1297,7 +1330,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1308,18 +1341,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: readv: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1566,7 +1599,8 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); } @@ -1601,7 +1635,7 @@ 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); - state = runtime->status->state; + state = runtime->state; snd_pcm_stream_unlock_irq(substream); if (state != SNDRV_PCM_STATE_RUNNING) { set_current_state(TASK_RUNNING); @@ -1638,13 +1672,14 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) runtime = substream->runtime; if (atomic_read(&substream->mmap_count)) goto __direct; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; atomic_inc(&runtime->oss.rw_ref); if (mutex_lock_interruptible(&runtime->oss.params_lock)) { atomic_dec(&runtime->oss.rw_ref); return -ERESTARTSYS; } + err = snd_pcm_oss_make_ready_locked(substream); + if (err < 0) + goto unlock; format = snd_pcm_oss_format_from(runtime->oss.format); width = snd_pcm_format_physical_width(format); if (runtime->oss.buffer_used > 0) { @@ -1704,7 +1739,8 @@ unlock: substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); @@ -1751,7 +1787,8 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.rate; } @@ -1788,7 +1825,8 @@ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.channels; } @@ -1798,7 +1836,8 @@ static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.period_bytes; } @@ -1813,7 +1852,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) const struct snd_mask *format_mask; int fmt; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; if (atomic_read(&substream->mmap_count)) direct = 1; @@ -1883,7 +1923,8 @@ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.format; } @@ -1934,11 +1975,15 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) { struct snd_pcm_runtime *runtime; + int fragshift; runtime = substream->runtime; if (runtime->oss.subdivision || runtime->oss.fragshift) return -EINVAL; - runtime->oss.fragshift = val & 0xffff; + fragshift = val & 0xffff; + if (fragshift >= 25) /* should be large enough */ + return -EINVAL; + runtime->oss.fragshift = fragshift; runtime->oss.maxfrags = (val >> 16) & 0xffff; if (runtime->oss.fragshift < 4) /* < 16 */ runtime->oss.fragshift = 4; @@ -2032,18 +2077,20 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr int err, cmd; #ifdef OSS_DEBUG - pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); + pr_debug("pcm_oss: trigger = 0x%x\n", trigger); #endif psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (psubstream) { - if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) + err = snd_pcm_oss_make_ready(psubstream); + if (err < 0) return err; } if (csubstream) { - if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) + err = snd_pcm_oss_make_ready(csubstream); + if (err < 0) return err; } if (psubstream) { @@ -2130,7 +2177,8 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) @@ -2157,7 +2205,8 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream substream = pcm_oss_file->streams[stream]; if (substream == NULL) return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) { @@ -2228,9 +2277,11 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre return -EINVAL; runtime = substream->runtime; - if (runtime->oss.params && - (err = snd_pcm_oss_change_params(substream, false)) < 0) - return err; + if (runtime->oss.params) { + err = snd_pcm_oss_change_params(substream, false); + if (err < 0) + return err; + } info.fragsize = runtime->oss.period_bytes; info.fragstotal = runtime->periods; @@ -2312,13 +2363,7 @@ static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; - kvfree(runtime->oss.buffer); - runtime->oss.buffer = NULL; -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - snd_pcm_oss_plugin_clear(substream); -#endif + snd_pcm_oss_release_buffers(substream); substream->oss.oss = 0; } @@ -2590,7 +2635,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDCTL_DSP_SPEED: if (get_user(res, p)) return -EFAULT; - if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) + res = snd_pcm_oss_set_rate(pcm_oss_file, res); + if (res < 0) return res; return put_user(res, p); case SOUND_PCM_READ_RATE: @@ -2602,7 +2648,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (get_user(res, p)) return -EFAULT; res = res > 0 ? 2 : 1; - if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) + res = snd_pcm_oss_set_channels(pcm_oss_file, res); + if (res < 0) return res; return put_user(--res, p); case SNDCTL_DSP_GETBLKSIZE: @@ -2807,8 +2854,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) 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 && - (runtime->status->state != SNDRV_PCM_STATE_RUNNING || + if (runtime->state != SNDRV_PCM_STATE_DRAINING && + (runtime->state != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_playback_ready(psubstream))) mask |= EPOLLOUT | EPOLLWRNORM; snd_pcm_stream_unlock_irq(psubstream); @@ -2818,7 +2865,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) 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 || + ostate = runtime->state; + if (ostate != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_capture_ready(csubstream)) mask |= EPOLLIN | EPOLLRDNORM; snd_pcm_stream_unlock_irq(csubstream); @@ -2850,7 +2898,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream) break; - /* Fall through */ + fallthrough; case VM_READ: substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; break; @@ -2875,7 +2923,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) if (runtime->oss.params) { /* use mutex_trylock() for params_lock for avoiding a deadlock - * between mmap_sem and params_lock taken by + * between mmap_lock and params_lock taken by * copy_from/to_user() in snd_pcm_oss_write/read() */ err = snd_pcm_oss_change_params(substream, true); @@ -3032,7 +3080,8 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) 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) { + entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root); + if (entry) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->mode = S_IFREG | 0644; entry->c.text.read = snd_pcm_oss_proc_read; @@ -3058,8 +3107,12 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) } } #else /* !CONFIG_SND_VERBOSE_PROCFS */ -#define snd_pcm_oss_proc_init(pcm) -#define snd_pcm_oss_proc_done(pcm) +static inline void snd_pcm_oss_proc_init(struct snd_pcm *pcm) +{ +} +static inline void snd_pcm_oss_proc_done(struct snd_pcm *pcm) +{ +} #endif /* CONFIG_SND_VERBOSE_PROCFS */ /* @@ -3176,7 +3229,8 @@ static int __init alsa_pcm_oss_init(void) adsp_map[i] = 1; } } - if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) + err = snd_pcm_notify(&snd_pcm_oss_notify, 0); + if (err < 0) return err; return 0; } diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 752d078908e9..82e180c776ae 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -59,9 +59,13 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t } else { format = &plugin->dst_format; } - if ((width = snd_pcm_format_physical_width(format->format)) < 0) + width = snd_pcm_format_physical_width(format->format); + if (width < 0) return width; - size = frames * format->channels * width; + size = array3_size(frames, format->channels, width); + /* check for too large period size once again */ + if (size > 1024 * 1024) + return -ENOMEM; if (snd_BUG_ON(size % 8)) return -ENXIO; size /= 8; @@ -196,82 +200,78 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin) return 0; } -snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames) +static snd_pcm_sframes_t calc_dst_frames(struct snd_pcm_substream *plug, + snd_pcm_sframes_t frames, + bool check_size) { - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - int stream; + struct snd_pcm_plugin *plugin, *plugin_next; - if (snd_BUG_ON(!plug)) - return -ENXIO; - if (drv_frames == 0) - return 0; - stream = snd_pcm_plug_stream(plug); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_last(plug); - while (plugin && drv_frames > 0) { - if (drv_frames > plugin->buf_frames) - drv_frames = plugin->buf_frames; - plugin_prev = plugin->prev; - if (plugin->src_frames) - drv_frames = plugin->src_frames(plugin, drv_frames); - plugin = plugin_prev; + plugin = snd_pcm_plug_first(plug); + while (plugin && frames > 0) { + plugin_next = plugin->next; + if (check_size && plugin->buf_frames && + frames > plugin->buf_frames) + frames = plugin->buf_frames; + if (plugin->dst_frames) { + frames = plugin->dst_frames(plugin, frames); + if (frames < 0) + return frames; } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_first(plug); - while (plugin && drv_frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) - drv_frames = plugin->dst_frames(plugin, drv_frames); - if (drv_frames > plugin->buf_frames) - drv_frames = plugin->buf_frames; - plugin = plugin_next; + plugin = plugin_next; + } + return frames; +} + +static snd_pcm_sframes_t calc_src_frames(struct snd_pcm_substream *plug, + snd_pcm_sframes_t frames, + bool check_size) +{ + struct snd_pcm_plugin *plugin, *plugin_prev; + + plugin = snd_pcm_plug_last(plug); + while (plugin && frames > 0) { + plugin_prev = plugin->prev; + if (plugin->src_frames) { + frames = plugin->src_frames(plugin, frames); + if (frames < 0) + return frames; } - } else + if (check_size && plugin->buf_frames && + frames > plugin->buf_frames) + frames = plugin->buf_frames; + plugin = plugin_prev; + } + return frames; +} + +snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames) +{ + if (snd_BUG_ON(!plug)) + return -ENXIO; + switch (snd_pcm_plug_stream(plug)) { + case SNDRV_PCM_STREAM_PLAYBACK: + return calc_src_frames(plug, drv_frames, false); + case SNDRV_PCM_STREAM_CAPTURE: + return calc_dst_frames(plug, drv_frames, false); + default: snd_BUG(); - return drv_frames; + return -EINVAL; + } } snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames) { - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - snd_pcm_sframes_t frames; - int stream; - if (snd_BUG_ON(!plug)) return -ENXIO; - if (clt_frames == 0) - return 0; - frames = clt_frames; - stream = snd_pcm_plug_stream(plug); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) { - frames = plugin->dst_frames(plugin, frames); - if (frames < 0) - return frames; - } - if (frames > plugin->buf_frames) - frames = plugin->buf_frames; - plugin = plugin_next; - } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_last(plug); - while (plugin) { - if (frames > plugin->buf_frames) - frames = plugin->buf_frames; - plugin_prev = plugin->prev; - if (plugin->src_frames) { - frames = plugin->src_frames(plugin, frames); - if (frames < 0) - return frames; - } - plugin = plugin_prev; - } - } else + switch (snd_pcm_plug_stream(plug)) { + case SNDRV_PCM_STREAM_PLAYBACK: + return calc_dst_frames(plug, clt_frames, false); + case SNDRV_PCM_STREAM_CAPTURE: + return calc_src_frames(plug, clt_frames, false); + default: snd_BUG(); - return frames; + return -EINVAL; + } } static int snd_pcm_plug_formats(const struct snd_mask *mask, @@ -361,7 +361,7 @@ snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, if (snd_mask_test(format_mask, (__force int)format1)) return format1; } - /* fall through */ + fallthrough; default: return (__force snd_pcm_format_t)-EINVAL; } @@ -576,7 +576,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu } v = plugin->buf_channels; *channels = v; - if ((width = snd_pcm_format_physical_width(format->format)) < 0) + width = snd_pcm_format_physical_width(format->format); + if (width < 0) return width; nchannels = format->channels; if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && @@ -604,16 +605,17 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st while (plugin) { if (frames <= 0) return frames; - if ((next = plugin->next) != NULL) { + next = plugin->next; + if (next) { snd_pcm_sframes_t frames1 = frames; if (plugin->dst_frames) { frames1 = plugin->dst_frames(plugin, frames); if (frames1 <= 0) return frames1; } - if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { + err = next->client_channels(next, frames1, &dst_channels); + if (err < 0) return err; - } if (err != frames1) { frames = err; if (plugin->src_frames) { @@ -625,12 +627,13 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st } else dst_channels = NULL; pdprintf("write plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) + frames = plugin->transfer(plugin, src_channels, dst_channels, frames); + if (frames < 0) return frames; src_channels = dst_channels; plugin = next; } - return snd_pcm_plug_client_size(plug, frames); + return calc_src_frames(plug, frames, true); } snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size) @@ -640,23 +643,25 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str snd_pcm_sframes_t frames = size; int err; - frames = snd_pcm_plug_slave_size(plug, frames); + frames = calc_src_frames(plug, frames, true); if (frames < 0) return frames; src_channels = NULL; plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { - if ((next = plugin->next) != NULL) { - if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { + next = plugin->next; + if (next) { + err = plugin->client_channels(plugin, frames, &dst_channels); + if (err < 0) return err; - } frames = err; } else { dst_channels = dst_channels_final; } pdprintf("read plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) + frames = plugin->transfer(plugin, src_channels, dst_channels, frames); + if (frames < 0) return frames; plugin = next; src_channels = dst_channels; diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index 8d2f7a4e3ab6..46e273bd4a78 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -64,7 +64,7 @@ struct snd_pcm_plugin { char *buf; snd_pcm_uframes_t buf_frames; struct snd_pcm_plugin_channel *buf_channels; - char extra_data[0]; + char extra_data[]; }; int snd_pcm_plugin_build(struct snd_pcm_substream *handle, diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c index 7cd09cef6961..98269119347f 100644 --- a/sound/core/oss/rate.c +++ b/sound/core/oss/rate.c @@ -47,7 +47,7 @@ struct rate_priv { unsigned int pos; rate_f func; snd_pcm_sframes_t old_src_frames, old_dst_frames; - struct rate_channel channels[0]; + struct rate_channel channels[]; }; static void rate_init(struct snd_pcm_plugin *plugin) @@ -193,7 +193,7 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_ if (plugin->src_format.rate < plugin->dst_format.rate) { res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); } else { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); + res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch); } if (data->old_src_frames > 0) { snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames; @@ -224,7 +224,7 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_ return 0; data = (struct rate_priv *)plugin->extra_data; if (plugin->src_format.rate < plugin->dst_format.rate) { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); + res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch); } else { res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); } |