ALSA: pcm: Add an ioctl to specify the supported protocol version
authorTakashi Iwai <tiwai@suse.de>
Mon, 19 Jun 2017 21:11:54 +0000 (23:11 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 27 Jun 2017 11:55:46 +0000 (13:55 +0200)
We have an ioctl to inform the PCM protocol version the running kernel
supports, but there is no way to know which protocol version the
user-space can understand.  This lack of information caused headaches
in the past when we tried to extend the ABI.  For example, because we
couldn't guarantee the validity of the reserved bytes, we had to
introduce a new ioctl SNDRV_PCM_IOCTL_STATUS_EXT for assigning a few
new fields in the formerly reserved bits.  If we could know that it's
a new alsa-lib, we could assume the availability of the new fields,
thus we could have reused the existing SNDRV_PCM_IOCTL_STATUS.

In order to improve the ABI extensibility, this patch adds a new ioctl
for user-space to inform its supporting protocol version to the
kernel.  By reporting the supported protocol from user-space, the
kernel can judge which feature should be provided and which not.

With the addition of the new ioctl, the PCM protocol version is bumped
to 2.0.14, too.  User-space checks the kernel protocol version via
SNDRV_PCM_INFO_PVERSION, then it sets the supported version back via
SNDRV_PCM_INFO_USER_PVERSION.

Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/pcm.h
include/uapi/sound/asound.h
sound/core/pcm_compat.c
sound/core/pcm_native.c

index 5a22075c5fcf91a9f3d2000e82d9d2ef5a633c61..24febf9e177c4b80547c9fd417d687537483ab5a 100644 (file)
@@ -218,6 +218,7 @@ struct snd_pcm_ops {
 struct snd_pcm_file {
        struct snd_pcm_substream *substream;
        int no_compat_mmap;
+       unsigned int user_pversion;     /* supported protocol version */
 };
 
 struct snd_pcm_hw_rule;
index 7eee52eb7462cb4f5a19293c39a27e1dc89bd72c..1949923a40bf98bd8cfedc59ff67eca6dc3e1c8a 100644 (file)
@@ -152,7 +152,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 13)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 14)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -564,6 +564,7 @@ enum {
 #define SNDRV_PCM_IOCTL_INFO           _IOR('A', 0x01, struct snd_pcm_info)
 #define SNDRV_PCM_IOCTL_TSTAMP         _IOW('A', 0x02, int)
 #define SNDRV_PCM_IOCTL_TTSTAMP                _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_USER_PVERSION  _IOW('A', 0x04, int)
 #define SNDRV_PCM_IOCTL_HW_REFINE      _IOWR('A', 0x10, struct snd_pcm_hw_params)
 #define SNDRV_PCM_IOCTL_HW_PARAMS      _IOWR('A', 0x11, struct snd_pcm_hw_params)
 #define SNDRV_PCM_IOCTL_HW_FREE                _IO('A', 0x12)
index 8a0f8d51e95d12e187a4640482e8aa99ae750050..10f537f4d73536f49cdea0b02447a497f7af7b03 100644 (file)
@@ -676,6 +676,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_PCM_IOCTL_INFO:
        case SNDRV_PCM_IOCTL_TSTAMP:
        case SNDRV_PCM_IOCTL_TTSTAMP:
+       case SNDRV_PCM_IOCTL_USER_PVERSION:
        case SNDRV_PCM_IOCTL_HWSYNC:
        case SNDRV_PCM_IOCTL_PREPARE:
        case SNDRV_PCM_IOCTL_RESET:
index 9ade0c8b54a328a5d9767340d34cbf94038d1eec..1c53d93e68f298a352cee0cc1fb505477d7edd4b 100644 (file)
@@ -2770,6 +2770,8 @@ 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;
+
        switch (cmd) {
        case SNDRV_PCM_IOCTL_PVERSION:
                return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -2779,6 +2781,11 @@ static int snd_pcm_common_ioctl(struct file *file,
                return 0;
        case SNDRV_PCM_IOCTL_TTSTAMP:
                return snd_pcm_tstamp(substream, arg);
+       case SNDRV_PCM_IOCTL_USER_PVERSION:
+               if (get_user(pcm_file->user_pversion,
+                            (unsigned int __user *)arg))
+                       return -EFAULT;
+               return 0;
        case SNDRV_PCM_IOCTL_HW_REFINE:
                return snd_pcm_hw_refine_user(substream, arg);
        case SNDRV_PCM_IOCTL_HW_PARAMS: