LCOV - code coverage report
Current view: top level - sound/core - pcm_compat.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 205 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 9 0.0 %
Branches: 0 162 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *   32bit -> 64bit ioctl wrapper for PCM API
       4                 :            :  *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
       5                 :            :  */
       6                 :            : 
       7                 :            : /* This file included from pcm_native.c */
       8                 :            : 
       9                 :            : #include <linux/compat.h>
      10                 :            : #include <linux/slab.h>
      11                 :            : 
      12                 :          0 : static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
      13                 :            :                                       s32 __user *src)
      14                 :            : {
      15                 :          0 :         snd_pcm_sframes_t delay;
      16                 :          0 :         int err;
      17                 :            : 
      18                 :          0 :         err = snd_pcm_delay(substream, &delay);
      19         [ #  # ]:          0 :         if (err)
      20                 :            :                 return err;
      21         [ #  # ]:          0 :         if (put_user(delay, src))
      22                 :          0 :                 return -EFAULT;
      23                 :            :         return 0;
      24                 :            : }
      25                 :            : 
      26                 :          0 : static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
      27                 :            :                                        u32 __user *src)
      28                 :            : {
      29                 :          0 :         snd_pcm_uframes_t frames;
      30                 :          0 :         int err;
      31                 :            : 
      32         [ #  # ]:          0 :         if (get_user(frames, src))
      33                 :            :                 return -EFAULT;
      34                 :          0 :         err = snd_pcm_rewind(substream, frames);
      35         [ #  # ]:          0 :         if (put_user(err, src))
      36                 :            :                 return -EFAULT;
      37                 :          0 :         return err < 0 ? err : 0;
      38                 :            : }
      39                 :            : 
      40                 :          0 : static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
      41                 :            :                                        u32 __user *src)
      42                 :            : {
      43                 :          0 :         snd_pcm_uframes_t frames;
      44                 :          0 :         int err;
      45                 :            : 
      46         [ #  # ]:          0 :         if (get_user(frames, src))
      47                 :            :                 return -EFAULT;
      48                 :          0 :         err = snd_pcm_forward(substream, frames);
      49         [ #  # ]:          0 :         if (put_user(err, src))
      50                 :            :                 return -EFAULT;
      51                 :          0 :         return err < 0 ? err : 0;
      52                 :            : }
      53                 :            : 
      54                 :            : struct snd_pcm_hw_params32 {
      55                 :            :         u32 flags;
      56                 :            :         struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
      57                 :            :         struct snd_mask mres[5];        /* reserved masks */
      58                 :            :         struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
      59                 :            :         struct snd_interval ires[9];    /* reserved intervals */
      60                 :            :         u32 rmask;
      61                 :            :         u32 cmask;
      62                 :            :         u32 info;
      63                 :            :         u32 msbits;
      64                 :            :         u32 rate_num;
      65                 :            :         u32 rate_den;
      66                 :            :         u32 fifo_size;
      67                 :            :         unsigned char reserved[64];
      68                 :            : };
      69                 :            : 
      70                 :            : struct snd_pcm_sw_params32 {
      71                 :            :         s32 tstamp_mode;
      72                 :            :         u32 period_step;
      73                 :            :         u32 sleep_min;
      74                 :            :         u32 avail_min;
      75                 :            :         u32 xfer_align;
      76                 :            :         u32 start_threshold;
      77                 :            :         u32 stop_threshold;
      78                 :            :         u32 silence_threshold;
      79                 :            :         u32 silence_size;
      80                 :            :         u32 boundary;
      81                 :            :         u32 proto;
      82                 :            :         u32 tstamp_type;
      83                 :            :         unsigned char reserved[56];
      84                 :            : };
      85                 :            : 
      86                 :          0 : static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
      87                 :            :                                           struct snd_pcm_sw_params32 __user *src)
      88                 :            : {
      89                 :          0 :         struct snd_pcm_sw_params params;
      90                 :          0 :         snd_pcm_uframes_t boundary;
      91                 :          0 :         int err;
      92                 :            : 
      93                 :          0 :         memset(&params, 0, sizeof(params));
      94         [ #  # ]:          0 :         if (get_user(params.tstamp_mode, &src->tstamp_mode) ||
      95         [ #  # ]:          0 :             get_user(params.period_step, &src->period_step) ||
      96         [ #  # ]:          0 :             get_user(params.sleep_min, &src->sleep_min) ||
      97         [ #  # ]:          0 :             get_user(params.avail_min, &src->avail_min) ||
      98         [ #  # ]:          0 :             get_user(params.xfer_align, &src->xfer_align) ||
      99         [ #  # ]:          0 :             get_user(params.start_threshold, &src->start_threshold) ||
     100         [ #  # ]:          0 :             get_user(params.stop_threshold, &src->stop_threshold) ||
     101         [ #  # ]:          0 :             get_user(params.silence_threshold, &src->silence_threshold) ||
     102         [ #  # ]:          0 :             get_user(params.silence_size, &src->silence_size) ||
     103         [ #  # ]:          0 :             get_user(params.tstamp_type, &src->tstamp_type) ||
     104         [ #  # ]:          0 :             get_user(params.proto, &src->proto))
     105                 :          0 :                 return -EFAULT;
     106                 :            :         /*
     107                 :            :          * Check silent_size parameter.  Since we have 64bit boundary,
     108                 :            :          * silence_size must be compared with the 32bit boundary.
     109                 :            :          */
     110         [ #  # ]:          0 :         boundary = recalculate_boundary(substream->runtime);
     111   [ #  #  #  # ]:          0 :         if (boundary && params.silence_size >= boundary)
     112                 :          0 :                 params.silence_size = substream->runtime->boundary;
     113                 :          0 :         err = snd_pcm_sw_params(substream, &params);
     114         [ #  # ]:          0 :         if (err < 0)
     115                 :            :                 return err;
     116   [ #  #  #  # ]:          0 :         if (boundary && put_user(boundary, &src->boundary))
     117                 :          0 :                 return -EFAULT;
     118                 :            :         return err;
     119                 :            : }
     120                 :            : 
     121                 :            : struct snd_pcm_channel_info32 {
     122                 :            :         u32 channel;
     123                 :            :         u32 offset;
     124                 :            :         u32 first;
     125                 :            :         u32 step;
     126                 :            : };
     127                 :            : 
     128                 :          0 : static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream,
     129                 :            :                                              struct snd_pcm_channel_info32 __user *src)
     130                 :            : {
     131                 :          0 :         struct snd_pcm_channel_info info;
     132                 :          0 :         int err;
     133                 :            : 
     134         [ #  # ]:          0 :         if (get_user(info.channel, &src->channel) ||
     135         [ #  # ]:          0 :             get_user(info.offset, &src->offset) ||
     136         [ #  # ]:          0 :             get_user(info.first, &src->first) ||
     137         [ #  # ]:          0 :             get_user(info.step, &src->step))
     138                 :          0 :                 return -EFAULT;
     139                 :          0 :         err = snd_pcm_channel_info(substream, &info);
     140         [ #  # ]:          0 :         if (err < 0)
     141                 :            :                 return err;
     142         [ #  # ]:          0 :         if (put_user(info.channel, &src->channel) ||
     143         [ #  # ]:          0 :             put_user(info.offset, &src->offset) ||
     144         [ #  # ]:          0 :             put_user(info.first, &src->first) ||
     145         [ #  # ]:          0 :             put_user(info.step, &src->step))
     146                 :          0 :                 return -EFAULT;
     147                 :            :         return err;
     148                 :            : }
     149                 :            : 
     150                 :            : #ifdef CONFIG_X86_X32
     151                 :            : /* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */
     152                 :            : static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
     153                 :            :                                      struct snd_pcm_channel_info __user *src);
     154                 :            : #define snd_pcm_ioctl_channel_info_x32(s, p)    \
     155                 :            :         snd_pcm_channel_info_user(s, p)
     156                 :            : #endif /* CONFIG_X86_X32 */
     157                 :            : 
     158                 :            : struct compat_snd_pcm_status64 {
     159                 :            :         snd_pcm_state_t state;
     160                 :            :         u8 rsvd[4]; /* alignment */
     161                 :            :         s64 trigger_tstamp_sec;
     162                 :            :         s64 trigger_tstamp_nsec;
     163                 :            :         s64 tstamp_sec;
     164                 :            :         s64 tstamp_nsec;
     165                 :            :         u32 appl_ptr;
     166                 :            :         u32 hw_ptr;
     167                 :            :         s32 delay;
     168                 :            :         u32 avail;
     169                 :            :         u32 avail_max;
     170                 :            :         u32 overrange;
     171                 :            :         snd_pcm_state_t suspended_state;
     172                 :            :         u32 audio_tstamp_data;
     173                 :            :         s64 audio_tstamp_sec;
     174                 :            :         s64 audio_tstamp_nsec;
     175                 :            :         s64 driver_tstamp_sec;
     176                 :            :         s64 driver_tstamp_nsec;
     177                 :            :         u32 audio_tstamp_accuracy;
     178                 :            :         unsigned char reserved[52-4*sizeof(s64)];
     179                 :            : } __packed;
     180                 :            : 
     181                 :          0 : static int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream,
     182                 :            :                                         struct compat_snd_pcm_status64 __user *src,
     183                 :            :                                         bool ext)
     184                 :            : {
     185                 :          0 :         struct snd_pcm_status64 status;
     186                 :          0 :         struct compat_snd_pcm_status64 compat_status64;
     187                 :          0 :         int err;
     188                 :            : 
     189                 :          0 :         memset(&status, 0, sizeof(status));
     190                 :          0 :         memset(&compat_status64, 0, sizeof(compat_status64));
     191                 :            :         /*
     192                 :            :          * with extension, parameters are read/write,
     193                 :            :          * get audio_tstamp_data from user,
     194                 :            :          * ignore rest of status structure
     195                 :            :          */
     196   [ #  #  #  # ]:          0 :         if (ext && get_user(status.audio_tstamp_data,
     197                 :            :                                 (u32 __user *)(&src->audio_tstamp_data)))
     198                 :            :                 return -EFAULT;
     199                 :          0 :         err = snd_pcm_status64(substream, &status);
     200         [ #  # ]:          0 :         if (err < 0)
     201                 :            :                 return err;
     202                 :            : 
     203         [ #  # ]:          0 :         if (clear_user(src, sizeof(*src)))
     204                 :            :                 return -EFAULT;
     205                 :            : 
     206                 :          0 :         compat_status64 = (struct compat_snd_pcm_status64) {
     207                 :          0 :                 .state = status.state,
     208                 :          0 :                 .trigger_tstamp_sec = status.trigger_tstamp_sec,
     209                 :          0 :                 .trigger_tstamp_nsec = status.trigger_tstamp_nsec,
     210                 :          0 :                 .tstamp_sec = status.tstamp_sec,
     211                 :          0 :                 .tstamp_nsec = status.tstamp_nsec,
     212                 :          0 :                 .appl_ptr = status.appl_ptr,
     213                 :          0 :                 .hw_ptr = status.hw_ptr,
     214                 :          0 :                 .delay = status.delay,
     215                 :          0 :                 .avail = status.avail,
     216                 :          0 :                 .avail_max = status.avail_max,
     217                 :          0 :                 .overrange = status.overrange,
     218                 :          0 :                 .suspended_state = status.suspended_state,
     219                 :          0 :                 .audio_tstamp_data = status.audio_tstamp_data,
     220                 :          0 :                 .audio_tstamp_sec = status.audio_tstamp_sec,
     221                 :          0 :                 .audio_tstamp_nsec = status.audio_tstamp_nsec,
     222                 :            :                 .driver_tstamp_sec = status.audio_tstamp_sec,
     223                 :            :                 .driver_tstamp_nsec = status.audio_tstamp_nsec,
     224                 :          0 :                 .audio_tstamp_accuracy = status.audio_tstamp_accuracy,
     225                 :            :         };
     226                 :            : 
     227         [ #  # ]:          0 :         if (copy_to_user(src, &compat_status64, sizeof(compat_status64)))
     228                 :          0 :                 return -EFAULT;
     229                 :            : 
     230                 :            :         return err;
     231                 :            : }
     232                 :            : 
     233                 :            : /* both for HW_PARAMS and HW_REFINE */
     234                 :          0 : static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
     235                 :            :                                           int refine, 
     236                 :            :                                           struct snd_pcm_hw_params32 __user *data32)
     237                 :            : {
     238                 :          0 :         struct snd_pcm_hw_params *data;
     239                 :          0 :         struct snd_pcm_runtime *runtime;
     240                 :          0 :         int err;
     241                 :            : 
     242         [ #  # ]:          0 :         if (! (runtime = substream->runtime))
     243                 :            :                 return -ENOTTY;
     244                 :            : 
     245                 :          0 :         data = kmalloc(sizeof(*data), GFP_KERNEL);
     246         [ #  # ]:          0 :         if (!data)
     247                 :            :                 return -ENOMEM;
     248                 :            : 
     249                 :            :         /* only fifo_size (RO from userspace) is different, so just copy all */
     250   [ #  #  #  # ]:          0 :         if (copy_from_user(data, data32, sizeof(*data32))) {
     251                 :          0 :                 err = -EFAULT;
     252                 :          0 :                 goto error;
     253                 :            :         }
     254                 :            : 
     255         [ #  # ]:          0 :         if (refine)
     256                 :          0 :                 err = snd_pcm_hw_refine(substream, data);
     257                 :            :         else
     258                 :          0 :                 err = snd_pcm_hw_params(substream, data);
     259         [ #  # ]:          0 :         if (err < 0)
     260                 :          0 :                 goto error;
     261   [ #  #  #  # ]:          0 :         if (copy_to_user(data32, data, sizeof(*data32)) ||
     262         [ #  # ]:          0 :             put_user(data->fifo_size, &data32->fifo_size)) {
     263                 :          0 :                 err = -EFAULT;
     264                 :          0 :                 goto error;
     265                 :            :         }
     266                 :            : 
     267         [ #  # ]:          0 :         if (! refine) {
     268         [ #  # ]:          0 :                 unsigned int new_boundary = recalculate_boundary(runtime);
     269         [ #  # ]:          0 :                 if (new_boundary)
     270                 :          0 :                         runtime->boundary = new_boundary;
     271                 :            :         }
     272                 :          0 :  error:
     273                 :          0 :         kfree(data);
     274                 :          0 :         return err;
     275                 :            : }
     276                 :            : 
     277                 :            : 
     278                 :            : /*
     279                 :            :  */
     280                 :            : struct snd_xferi32 {
     281                 :            :         s32 result;
     282                 :            :         u32 buf;
     283                 :            :         u32 frames;
     284                 :            : };
     285                 :            : 
     286                 :          0 : static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream,
     287                 :            :                                       int dir, struct snd_xferi32 __user *data32)
     288                 :            : {
     289                 :          0 :         compat_caddr_t buf;
     290                 :          0 :         u32 frames;
     291                 :          0 :         int err;
     292                 :            : 
     293         [ #  # ]:          0 :         if (! substream->runtime)
     294                 :            :                 return -ENOTTY;
     295         [ #  # ]:          0 :         if (substream->stream != dir)
     296                 :            :                 return -EINVAL;
     297         [ #  # ]:          0 :         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
     298                 :            :                 return -EBADFD;
     299                 :            : 
     300         [ #  # ]:          0 :         if (get_user(buf, &data32->buf) ||
     301         [ #  # ]:          0 :             get_user(frames, &data32->frames))
     302                 :          0 :                 return -EFAULT;
     303                 :            : 
     304         [ #  # ]:          0 :         if (dir == SNDRV_PCM_STREAM_PLAYBACK)
     305                 :          0 :                 err = snd_pcm_lib_write(substream, compat_ptr(buf), frames);
     306                 :            :         else
     307                 :          0 :                 err = snd_pcm_lib_read(substream, compat_ptr(buf), frames);
     308         [ #  # ]:          0 :         if (err < 0)
     309                 :            :                 return err;
     310                 :            :         /* copy the result */
     311         [ #  # ]:          0 :         if (put_user(err, &data32->result))
     312                 :          0 :                 return -EFAULT;
     313                 :            :         return 0;
     314                 :            : }
     315                 :            : 
     316                 :            : 
     317                 :            : /* snd_xfern needs remapping of bufs */
     318                 :            : struct snd_xfern32 {
     319                 :            :         s32 result;
     320                 :            :         u32 bufs;  /* this is void **; */
     321                 :            :         u32 frames;
     322                 :            : };
     323                 :            : 
     324                 :            : /*
     325                 :            :  * xfern ioctl nees to copy (up to) 128 pointers on stack.
     326                 :            :  * although we may pass the copied pointers through f_op->ioctl, but the ioctl
     327                 :            :  * handler there expands again the same 128 pointers on stack, so it is better
     328                 :            :  * to handle the function (calling pcm_readv/writev) directly in this handler.
     329                 :            :  */
     330                 :          0 : static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
     331                 :            :                                       int dir, struct snd_xfern32 __user *data32)
     332                 :            : {
     333                 :          0 :         compat_caddr_t buf;
     334                 :          0 :         compat_caddr_t __user *bufptr;
     335                 :          0 :         u32 frames;
     336                 :          0 :         void __user **bufs;
     337                 :          0 :         int err, ch, i;
     338                 :            : 
     339         [ #  # ]:          0 :         if (! substream->runtime)
     340                 :            :                 return -ENOTTY;
     341         [ #  # ]:          0 :         if (substream->stream != dir)
     342                 :            :                 return -EINVAL;
     343         [ #  # ]:          0 :         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
     344                 :            :                 return -EBADFD;
     345                 :            : 
     346         [ #  # ]:          0 :         if ((ch = substream->runtime->channels) > 128)
     347                 :            :                 return -EINVAL;
     348         [ #  # ]:          0 :         if (get_user(buf, &data32->bufs) ||
     349         [ #  # ]:          0 :             get_user(frames, &data32->frames))
     350                 :          0 :                 return -EFAULT;
     351                 :          0 :         bufptr = compat_ptr(buf);
     352                 :          0 :         bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
     353         [ #  # ]:          0 :         if (bufs == NULL)
     354                 :            :                 return -ENOMEM;
     355         [ #  # ]:          0 :         for (i = 0; i < ch; i++) {
     356                 :          0 :                 u32 ptr;
     357         [ #  # ]:          0 :                 if (get_user(ptr, bufptr)) {
     358                 :          0 :                         kfree(bufs);
     359                 :          0 :                         return -EFAULT;
     360                 :            :                 }
     361                 :          0 :                 bufs[i] = compat_ptr(ptr);
     362                 :          0 :                 bufptr++;
     363                 :            :         }
     364         [ #  # ]:          0 :         if (dir == SNDRV_PCM_STREAM_PLAYBACK)
     365                 :          0 :                 err = snd_pcm_lib_writev(substream, bufs, frames);
     366                 :            :         else
     367                 :          0 :                 err = snd_pcm_lib_readv(substream, bufs, frames);
     368         [ #  # ]:          0 :         if (err >= 0) {
     369         [ #  # ]:          0 :                 if (put_user(err, &data32->result))
     370                 :          0 :                         err = -EFAULT;
     371                 :            :         }
     372                 :          0 :         kfree(bufs);
     373                 :          0 :         return err;
     374                 :            : }
     375                 :            : 
     376                 :            : #ifdef CONFIG_X86_X32
     377                 :            : /* X32 ABI has 64bit timespec and 64bit alignment */
     378                 :            : struct snd_pcm_mmap_status_x32 {
     379                 :            :         snd_pcm_state_t state;
     380                 :            :         s32 pad1;
     381                 :            :         u32 hw_ptr;
     382                 :            :         u32 pad2; /* alignment */
     383                 :            :         s64 tstamp_sec;
     384                 :            :         s64 tstamp_nsec;
     385                 :            :         snd_pcm_state_t suspended_state;
     386                 :            :         s32 pad3;
     387                 :            :         s64 audio_tstamp_sec;
     388                 :            :         s64 audio_tstamp_nsec;
     389                 :            : } __packed;
     390                 :            : 
     391                 :            : struct snd_pcm_mmap_control_x32 {
     392                 :            :         u32 appl_ptr;
     393                 :            :         u32 avail_min;
     394                 :            : };
     395                 :            : 
     396                 :            : struct snd_pcm_sync_ptr_x32 {
     397                 :            :         u32 flags;
     398                 :            :         u32 rsvd; /* alignment */
     399                 :            :         union {
     400                 :            :                 struct snd_pcm_mmap_status_x32 status;
     401                 :            :                 unsigned char reserved[64];
     402                 :            :         } s;
     403                 :            :         union {
     404                 :            :                 struct snd_pcm_mmap_control_x32 control;
     405                 :            :                 unsigned char reserved[64];
     406                 :            :         } c;
     407                 :            : } __packed;
     408                 :            : 
     409                 :            : static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
     410                 :            :                                       struct snd_pcm_sync_ptr_x32 __user *src)
     411                 :            : {
     412                 :            :         struct snd_pcm_runtime *runtime = substream->runtime;
     413                 :            :         volatile struct snd_pcm_mmap_status *status;
     414                 :            :         volatile struct snd_pcm_mmap_control *control;
     415                 :            :         u32 sflags;
     416                 :            :         struct snd_pcm_mmap_control scontrol;
     417                 :            :         struct snd_pcm_mmap_status sstatus;
     418                 :            :         snd_pcm_uframes_t boundary;
     419                 :            :         int err;
     420                 :            : 
     421                 :            :         if (snd_BUG_ON(!runtime))
     422                 :            :                 return -EINVAL;
     423                 :            : 
     424                 :            :         if (get_user(sflags, &src->flags) ||
     425                 :            :             get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
     426                 :            :             get_user(scontrol.avail_min, &src->c.control.avail_min))
     427                 :            :                 return -EFAULT;
     428                 :            :         if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
     429                 :            :                 err = snd_pcm_hwsync(substream);
     430                 :            :                 if (err < 0)
     431                 :            :                         return err;
     432                 :            :         }
     433                 :            :         status = runtime->status;
     434                 :            :         control = runtime->control;
     435                 :            :         boundary = recalculate_boundary(runtime);
     436                 :            :         if (!boundary)
     437                 :            :                 boundary = 0x7fffffff;
     438                 :            :         snd_pcm_stream_lock_irq(substream);
     439                 :            :         /* FIXME: we should consider the boundary for the sync from app */
     440                 :            :         if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
     441                 :            :                 control->appl_ptr = scontrol.appl_ptr;
     442                 :            :         else
     443                 :            :                 scontrol.appl_ptr = control->appl_ptr % boundary;
     444                 :            :         if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
     445                 :            :                 control->avail_min = scontrol.avail_min;
     446                 :            :         else
     447                 :            :                 scontrol.avail_min = control->avail_min;
     448                 :            :         sstatus.state = status->state;
     449                 :            :         sstatus.hw_ptr = status->hw_ptr % boundary;
     450                 :            :         sstatus.tstamp = status->tstamp;
     451                 :            :         sstatus.suspended_state = status->suspended_state;
     452                 :            :         sstatus.audio_tstamp = status->audio_tstamp;
     453                 :            :         snd_pcm_stream_unlock_irq(substream);
     454                 :            :         if (put_user(sstatus.state, &src->s.status.state) ||
     455                 :            :             put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
     456                 :            :             put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
     457                 :            :             put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
     458                 :            :             put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
     459                 :            :             put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
     460                 :            :             put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
     461                 :            :             put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
     462                 :            :             put_user(scontrol.avail_min, &src->c.control.avail_min))
     463                 :            :                 return -EFAULT;
     464                 :            : 
     465                 :            :         return 0;
     466                 :            : }
     467                 :            : #endif /* CONFIG_X86_X32 */
     468                 :            : 
     469                 :            : /*
     470                 :            :  */
     471                 :            : enum {
     472                 :            :         SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
     473                 :            :         SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
     474                 :            :         SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
     475                 :            :         SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32),
     476                 :            :         SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
     477                 :            :         SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
     478                 :            :         SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
     479                 :            :         SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
     480                 :            :         SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
     481                 :            :         SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32),
     482                 :            :         SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
     483                 :            :         SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
     484                 :            :         SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
     485                 :            :         SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64),
     486                 :            :         SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64),
     487                 :            : #ifdef CONFIG_X86_X32
     488                 :            :         SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
     489                 :            :         SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
     490                 :            : #endif /* CONFIG_X86_X32 */
     491                 :            : };
     492                 :            : 
     493                 :          0 : static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
     494                 :            : {
     495                 :          0 :         struct snd_pcm_file *pcm_file;
     496                 :          0 :         struct snd_pcm_substream *substream;
     497         [ #  # ]:          0 :         void __user *argp = compat_ptr(arg);
     498                 :            : 
     499                 :          0 :         pcm_file = file->private_data;
     500         [ #  # ]:          0 :         if (! pcm_file)
     501                 :            :                 return -ENOTTY;
     502                 :          0 :         substream = pcm_file->substream;
     503         [ #  # ]:          0 :         if (! substream)
     504                 :            :                 return -ENOTTY;
     505                 :            : 
     506                 :            :         /*
     507                 :            :          * When PCM is used on 32bit mode, we need to disable
     508                 :            :          * mmap of the old PCM status/control records because
     509                 :            :          * of the size incompatibility.
     510                 :            :          */
     511                 :          0 :         pcm_file->no_compat_mmap = 1;
     512                 :            : 
     513   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     514                 :          0 :         case SNDRV_PCM_IOCTL_PVERSION:
     515                 :            :         case SNDRV_PCM_IOCTL_INFO:
     516                 :            :         case SNDRV_PCM_IOCTL_TSTAMP:
     517                 :            :         case SNDRV_PCM_IOCTL_TTSTAMP:
     518                 :            :         case SNDRV_PCM_IOCTL_USER_PVERSION:
     519                 :            :         case SNDRV_PCM_IOCTL_HWSYNC:
     520                 :            :         case SNDRV_PCM_IOCTL_PREPARE:
     521                 :            :         case SNDRV_PCM_IOCTL_RESET:
     522                 :            :         case SNDRV_PCM_IOCTL_START:
     523                 :            :         case SNDRV_PCM_IOCTL_DROP:
     524                 :            :         case SNDRV_PCM_IOCTL_DRAIN:
     525                 :            :         case SNDRV_PCM_IOCTL_PAUSE:
     526                 :            :         case SNDRV_PCM_IOCTL_HW_FREE:
     527                 :            :         case SNDRV_PCM_IOCTL_RESUME:
     528                 :            :         case SNDRV_PCM_IOCTL_XRUN:
     529                 :            :         case SNDRV_PCM_IOCTL_LINK:
     530                 :            :         case SNDRV_PCM_IOCTL_UNLINK:
     531                 :            :         case __SNDRV_PCM_IOCTL_SYNC_PTR32:
     532                 :          0 :                 return snd_pcm_common_ioctl(file, substream, cmd, argp);
     533                 :          0 :         case __SNDRV_PCM_IOCTL_SYNC_PTR64:
     534                 :            : #ifdef CONFIG_X86_X32
     535                 :            :                 if (in_x32_syscall())
     536                 :            :                         return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
     537                 :            : #endif /* CONFIG_X86_X32 */
     538                 :          0 :                 return snd_pcm_common_ioctl(file, substream, cmd, argp);
     539                 :          0 :         case SNDRV_PCM_IOCTL_HW_REFINE32:
     540                 :          0 :                 return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
     541                 :          0 :         case SNDRV_PCM_IOCTL_HW_PARAMS32:
     542                 :          0 :                 return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
     543                 :          0 :         case SNDRV_PCM_IOCTL_SW_PARAMS32:
     544                 :          0 :                 return snd_pcm_ioctl_sw_params_compat(substream, argp);
     545                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_COMPAT32:
     546                 :          0 :                 return snd_pcm_status_user32(substream, argp, false);
     547                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32:
     548                 :          0 :                 return snd_pcm_status_user32(substream, argp, true);
     549                 :          0 :         case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
     550                 :          0 :                 return snd_pcm_ioctl_channel_info_compat(substream, argp);
     551                 :          0 :         case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
     552                 :          0 :                 return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
     553                 :          0 :         case SNDRV_PCM_IOCTL_READI_FRAMES32:
     554                 :          0 :                 return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
     555                 :          0 :         case SNDRV_PCM_IOCTL_WRITEN_FRAMES32:
     556                 :          0 :                 return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
     557                 :          0 :         case SNDRV_PCM_IOCTL_READN_FRAMES32:
     558                 :          0 :                 return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
     559                 :            :         case SNDRV_PCM_IOCTL_DELAY32:
     560                 :          0 :                 return snd_pcm_ioctl_delay_compat(substream, argp);
     561                 :          0 :         case SNDRV_PCM_IOCTL_REWIND32:
     562                 :          0 :                 return snd_pcm_ioctl_rewind_compat(substream, argp);
     563                 :          0 :         case SNDRV_PCM_IOCTL_FORWARD32:
     564                 :          0 :                 return snd_pcm_ioctl_forward_compat(substream, argp);
     565                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_COMPAT64:
     566                 :          0 :                 return snd_pcm_status_user_compat64(substream, argp, false);
     567                 :          0 :         case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64:
     568                 :          0 :                 return snd_pcm_status_user_compat64(substream, argp, true);
     569                 :            : #ifdef CONFIG_X86_X32
     570                 :            :         case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
     571                 :            :                 return snd_pcm_ioctl_channel_info_x32(substream, argp);
     572                 :            : #endif /* CONFIG_X86_X32 */
     573                 :            :         }
     574                 :            : 
     575                 :            :         return -ENOIOCTLCMD;
     576                 :            : }

Generated by: LCOV version 1.14