ALSA: core: pass audio tstamp config from userspace in compat mode
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Fri, 13 Feb 2015 21:14:05 +0000 (15:14 -0600)
committerTakashi Iwai <tiwai@suse.de>
Fri, 20 Feb 2015 16:30:05 +0000 (17:30 +0100)
Let userspace select audio timestamp config, ignore and zero all
other fields
Use audio_tstamp_data to retrieve config and pass report back to
user space

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_compat.c

index 2d957ba635578758172c9d66addc181a3ce438a9..b48b434444ed0e0239936887a891d15da0054e00 100644 (file)
@@ -194,18 +194,30 @@ struct snd_pcm_status32 {
        u32 avail_max;
        u32 overrange;
        s32 suspended_state;
-       u32 reserved_alignment;
+       u32 audio_tstamp_data;
        struct compat_timespec audio_tstamp;
-       unsigned char reserved[56-sizeof(struct compat_timespec)];
+       struct compat_timespec driver_tstamp;
+       u32 audio_tstamp_accuracy;
+       unsigned char reserved[52-2*sizeof(struct compat_timespec)];
 } __attribute__((packed));
 
 
 static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_status32 __user *src)
+                                     struct snd_pcm_status32 __user *src,
+                                     bool ext)
 {
        struct snd_pcm_status status;
        int err;
 
+       memset(&status, 0, sizeof(status));
+       /*
+        * with extension, parameters are read/write,
+        * get audio_tstamp_data from user,
+        * ignore rest of status structure
+        */
+       if (ext && get_user(status.audio_tstamp_data,
+                               (u32 __user *)(&src->audio_tstamp_data)))
+               return -EFAULT;
        err = snd_pcm_status(substream, &status);
        if (err < 0)
                return err;
@@ -222,7 +234,10 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
            put_user(status.avail_max, &src->avail_max) ||
            put_user(status.overrange, &src->overrange) ||
            put_user(status.suspended_state, &src->suspended_state) ||
-           compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp))
+           put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
+           compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
+           compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
+           put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
                return -EFAULT;
 
        return err;
@@ -457,6 +472,7 @@ enum {
        SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
        SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
        SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
+       SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
        SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
        SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
        SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
@@ -517,7 +533,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_PCM_IOCTL_SW_PARAMS32:
                return snd_pcm_ioctl_sw_params_compat(substream, argp);
        case SNDRV_PCM_IOCTL_STATUS32:
-               return snd_pcm_status_user_compat(substream, argp);
+               return snd_pcm_status_user_compat(substream, argp, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT32:
+               return snd_pcm_status_user_compat(substream, argp, true);
        case SNDRV_PCM_IOCTL_SYNC_PTR32:
                return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
        case SNDRV_PCM_IOCTL_CHANNEL_INFO32: