ALSA: pcm: Unify ioctl functions for playback and capture streams
authorTakashi Iwai <tiwai@suse.de>
Wed, 30 Aug 2017 13:39:32 +0000 (15:39 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 30 Aug 2017 18:44:55 +0000 (20:44 +0200)
Some ioctl functions are implemented individually for both playback
and capture streams although most of the codes are identical with just
a few different stream-specific function calls.  This patch unifies
these places, removes the superfluous trivial check and flattens the
call paths as a cleanup.  Meanwhile, for better readability, some
codes (e.g. xfer ioctls or forward/rewind ioctls) are factored out as
functions.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_compat.c
sound/core/pcm_native.c

index 10f537f..3a1cc7b 100644 (file)
@@ -689,10 +689,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_PCM_IOCTL_XRUN:
        case SNDRV_PCM_IOCTL_LINK:
        case SNDRV_PCM_IOCTL_UNLINK:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
-               else
-                       return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
+               return snd_pcm_common_ioctl(file, substream, cmd, argp);
        case SNDRV_PCM_IOCTL_HW_REFINE32:
                return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
        case SNDRV_PCM_IOCTL_HW_PARAMS32:
index 621142e..2fec2fe 100644 (file)
@@ -2761,14 +2761,103 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
        runtime->tstamp_type = arg;
        return 0;
 }
-               
-static int snd_pcm_common_ioctl1(struct file *file,
+
+static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
+                                     struct snd_xferi __user *_xferi)
+{
+       struct snd_xferi xferi;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       snd_pcm_sframes_t result;
+
+       if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+               return -EBADFD;
+       if (put_user(0, &_xferi->result))
+               return -EFAULT;
+       if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
+               return -EFAULT;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
+       else
+               result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
+       __put_user(result, &_xferi->result);
+       return result < 0 ? result : 0;
+}
+
+static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
+                                     struct snd_xfern __user *_xfern)
+{
+       struct snd_xfern xfern;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       void *bufs;
+       snd_pcm_sframes_t result;
+
+       if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+               return -EBADFD;
+       if (runtime->channels > 128)
+               return -EINVAL;
+       if (put_user(0, &_xfern->result))
+               return -EFAULT;
+       if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
+               return -EFAULT;
+
+       bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
+       if (IS_ERR(bufs))
+               return PTR_ERR(bufs);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
+       else
+               result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
+       kfree(bufs);
+       __put_user(result, &_xfern->result);
+       return result < 0 ? result : 0;
+}
+
+static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
+                               snd_pcm_uframes_t __user *_frames)
+{
+       snd_pcm_uframes_t frames;
+       snd_pcm_sframes_t result;
+
+       if (get_user(frames, _frames))
+               return -EFAULT;
+       if (put_user(0, _frames))
+               return -EFAULT;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               result = snd_pcm_playback_rewind(substream, frames);
+       else
+               result = snd_pcm_capture_rewind(substream, frames);
+       __put_user(result, _frames);
+       return result < 0 ? result : 0;
+}
+
+static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
+                                snd_pcm_uframes_t __user *_frames)
+{
+       snd_pcm_uframes_t frames;
+       snd_pcm_sframes_t result;
+
+       if (get_user(frames, _frames))
+               return -EFAULT;
+       if (put_user(0, _frames))
+               return -EFAULT;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               result = snd_pcm_playback_forward(substream, frames);
+       else
+               result = snd_pcm_capture_forward(substream, frames);
+       __put_user(result, _frames);
+       return result < 0 ? result : 0;
+}
+
+static int snd_pcm_common_ioctl(struct file *file,
                                 struct snd_pcm_substream *substream,
                                 unsigned int cmd, void __user *arg)
 {
        struct snd_pcm_file *pcm_file = file->private_data;
        int res;
 
+       if (PCM_RUNTIME_CHECK(substream))
+               return -ENXIO;
+
        res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
        if (res < 0)
                return res;
@@ -2844,187 +2933,23 @@ static int snd_pcm_common_ioctl1(struct file *file,
                return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
                                               substream,
                                               (int)(unsigned long)arg);
-       }
-       pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
-       return -ENOTTY;
-}
-
-static int snd_pcm_playback_ioctl1(struct file *file,
-                                  struct snd_pcm_substream *substream,
-                                  unsigned int cmd, void __user *arg)
-{
-       if (PCM_RUNTIME_CHECK(substream))
-               return -ENXIO;
-       if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
-               return -EINVAL;
-       switch (cmd) {
        case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
-       {
-               struct snd_xferi xferi;
-               struct snd_xferi __user *_xferi = arg;
-               struct snd_pcm_runtime *runtime = substream->runtime;
-               snd_pcm_sframes_t result;
-               if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-                       return -EBADFD;
-               if (put_user(0, &_xferi->result))
-                       return -EFAULT;
-               if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
-                       return -EFAULT;
-               result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
-               __put_user(result, &_xferi->result);
-               return result < 0 ? result : 0;
-       }
-       case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
-       {
-               struct snd_xfern xfern;
-               struct snd_xfern __user *_xfern = arg;
-               struct snd_pcm_runtime *runtime = substream->runtime;
-               void __user **bufs;
-               snd_pcm_sframes_t result;
-               if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-                       return -EBADFD;
-               if (runtime->channels > 128)
-                       return -EINVAL;
-               if (put_user(0, &_xfern->result))
-                       return -EFAULT;
-               if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
-                       return -EFAULT;
-
-               bufs = memdup_user(xfern.bufs,
-                                  sizeof(void *) * runtime->channels);
-               if (IS_ERR(bufs))
-                       return PTR_ERR(bufs);
-               result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
-               kfree(bufs);
-               __put_user(result, &_xfern->result);
-               return result < 0 ? result : 0;
-       }
-       case SNDRV_PCM_IOCTL_REWIND:
-       {
-               snd_pcm_uframes_t frames;
-               snd_pcm_uframes_t __user *_frames = arg;
-               snd_pcm_sframes_t result;
-               if (get_user(frames, _frames))
-                       return -EFAULT;
-               if (put_user(0, _frames))
-                       return -EFAULT;
-               result = snd_pcm_playback_rewind(substream, frames);
-               __put_user(result, _frames);
-               return result < 0 ? result : 0;
-       }
-       case SNDRV_PCM_IOCTL_FORWARD:
-       {
-               snd_pcm_uframes_t frames;
-               snd_pcm_uframes_t __user *_frames = arg;
-               snd_pcm_sframes_t result;
-               if (get_user(frames, _frames))
-                       return -EFAULT;
-               if (put_user(0, _frames))
-                       return -EFAULT;
-               result = snd_pcm_playback_forward(substream, frames);
-               __put_user(result, _frames);
-               return result < 0 ? result : 0;
-       }
-       }
-       return snd_pcm_common_ioctl1(file, substream, cmd, arg);
-}
-
-static int snd_pcm_capture_ioctl1(struct file *file,
-                                 struct snd_pcm_substream *substream,
-                                 unsigned int cmd, void __user *arg)
-{
-       if (PCM_RUNTIME_CHECK(substream))
-               return -ENXIO;
-       if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
-               return -EINVAL;
-       switch (cmd) {
        case SNDRV_PCM_IOCTL_READI_FRAMES:
-       {
-               struct snd_xferi xferi;
-               struct snd_xferi __user *_xferi = arg;
-               struct snd_pcm_runtime *runtime = substream->runtime;
-               snd_pcm_sframes_t result;
-               if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-                       return -EBADFD;
-               if (put_user(0, &_xferi->result))
-                       return -EFAULT;
-               if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
-                       return -EFAULT;
-               result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
-               __put_user(result, &_xferi->result);
-               return result < 0 ? result : 0;
-       }
+               return snd_pcm_xferi_frames_ioctl(substream, arg);
+       case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
        case SNDRV_PCM_IOCTL_READN_FRAMES:
-       {
-               struct snd_xfern xfern;
-               struct snd_xfern __user *_xfern = arg;
-               struct snd_pcm_runtime *runtime = substream->runtime;
-               void *bufs;
-               snd_pcm_sframes_t result;
-               if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-                       return -EBADFD;
-               if (runtime->channels > 128)
-                       return -EINVAL;
-               if (put_user(0, &_xfern->result))
-                       return -EFAULT;
-               if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
-                       return -EFAULT;
-
-               bufs = memdup_user(xfern.bufs,
-                                  sizeof(void *) * runtime->channels);
-               if (IS_ERR(bufs))
-                       return PTR_ERR(bufs);
-               result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
-               kfree(bufs);
-               __put_user(result, &_xfern->result);
-               return result < 0 ? result : 0;
-       }
+               return snd_pcm_xfern_frames_ioctl(substream, arg);
        case SNDRV_PCM_IOCTL_REWIND:
-       {
-               snd_pcm_uframes_t frames;
-               snd_pcm_uframes_t __user *_frames = arg;
-               snd_pcm_sframes_t result;
-               if (get_user(frames, _frames))
-                       return -EFAULT;
-               if (put_user(0, _frames))
-                       return -EFAULT;
-               result = snd_pcm_capture_rewind(substream, frames);
-               __put_user(result, _frames);
-               return result < 0 ? result : 0;
-       }
+               return snd_pcm_rewind_ioctl(substream, arg);
        case SNDRV_PCM_IOCTL_FORWARD:
-       {
-               snd_pcm_uframes_t frames;
-               snd_pcm_uframes_t __user *_frames = arg;
-               snd_pcm_sframes_t result;
-               if (get_user(frames, _frames))
-                       return -EFAULT;
-               if (put_user(0, _frames))
-                       return -EFAULT;
-               result = snd_pcm_capture_forward(substream, frames);
-               __put_user(result, _frames);
-               return result < 0 ? result : 0;
+               return snd_pcm_forward_ioctl(substream, arg);
        }
-       }
-       return snd_pcm_common_ioctl1(file, substream, cmd, arg);
-}
-
-static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-{
-       struct snd_pcm_file *pcm_file;
-
-       pcm_file = file->private_data;
-
-       if (((cmd >> 8) & 0xff) != 'A')
-               return -ENOTTY;
-
-       return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
-                                      (void __user *)arg);
+       pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd);
+       return -ENOTTY;
 }
 
-static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
+static long snd_pcm_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
 {
        struct snd_pcm_file *pcm_file;
 
@@ -3033,8 +2958,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
        if (((cmd >> 8) & 0xff) != 'A')
                return -ENOTTY;
 
-       return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
-                                     (void __user *)arg);
+       return snd_pcm_common_ioctl(file, pcm_file->substream, cmd,
+                                    (void __user *)arg);
 }
 
 /**
@@ -3775,7 +3700,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
                .release =              snd_pcm_release,
                .llseek =               no_llseek,
                .poll =                 snd_pcm_playback_poll,
-               .unlocked_ioctl =       snd_pcm_playback_ioctl,
+               .unlocked_ioctl =       snd_pcm_ioctl,
                .compat_ioctl =         snd_pcm_ioctl_compat,
                .mmap =                 snd_pcm_mmap,
                .fasync =               snd_pcm_fasync,
@@ -3789,7 +3714,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
                .release =              snd_pcm_release,
                .llseek =               no_llseek,
                .poll =                 snd_pcm_capture_poll,
-               .unlocked_ioctl =       snd_pcm_capture_ioctl,
+               .unlocked_ioctl =       snd_pcm_ioctl,
                .compat_ioctl =         snd_pcm_ioctl_compat,
                .mmap =                 snd_pcm_mmap,
                .fasync =               snd_pcm_fasync,