18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 32bit -> 64bit ioctl wrapper for PCM API 48c2ecf20Sopenharmony_ci * Copyright (c) by Takashi Iwai <tiwai@suse.de> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* This file included from pcm_native.c */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/compat.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, 138c2ecf20Sopenharmony_ci s32 __user *src) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci snd_pcm_sframes_t delay; 168c2ecf20Sopenharmony_ci int err; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci err = snd_pcm_delay(substream, &delay); 198c2ecf20Sopenharmony_ci if (err) 208c2ecf20Sopenharmony_ci return err; 218c2ecf20Sopenharmony_ci if (put_user(delay, src)) 228c2ecf20Sopenharmony_ci return -EFAULT; 238c2ecf20Sopenharmony_ci return 0; 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, 278c2ecf20Sopenharmony_ci u32 __user *src) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci snd_pcm_uframes_t frames; 308c2ecf20Sopenharmony_ci int err; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (get_user(frames, src)) 338c2ecf20Sopenharmony_ci return -EFAULT; 348c2ecf20Sopenharmony_ci err = snd_pcm_rewind(substream, frames); 358c2ecf20Sopenharmony_ci if (put_user(err, src)) 368c2ecf20Sopenharmony_ci return -EFAULT; 378c2ecf20Sopenharmony_ci return err < 0 ? err : 0; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream, 418c2ecf20Sopenharmony_ci u32 __user *src) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci snd_pcm_uframes_t frames; 448c2ecf20Sopenharmony_ci int err; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (get_user(frames, src)) 478c2ecf20Sopenharmony_ci return -EFAULT; 488c2ecf20Sopenharmony_ci err = snd_pcm_forward(substream, frames); 498c2ecf20Sopenharmony_ci if (put_user(err, src)) 508c2ecf20Sopenharmony_ci return -EFAULT; 518c2ecf20Sopenharmony_ci return err < 0 ? err : 0; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistruct snd_pcm_hw_params32 { 558c2ecf20Sopenharmony_ci u32 flags; 568c2ecf20Sopenharmony_ci struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ 578c2ecf20Sopenharmony_ci struct snd_mask mres[5]; /* reserved masks */ 588c2ecf20Sopenharmony_ci struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; 598c2ecf20Sopenharmony_ci struct snd_interval ires[9]; /* reserved intervals */ 608c2ecf20Sopenharmony_ci u32 rmask; 618c2ecf20Sopenharmony_ci u32 cmask; 628c2ecf20Sopenharmony_ci u32 info; 638c2ecf20Sopenharmony_ci u32 msbits; 648c2ecf20Sopenharmony_ci u32 rate_num; 658c2ecf20Sopenharmony_ci u32 rate_den; 668c2ecf20Sopenharmony_ci u32 fifo_size; 678c2ecf20Sopenharmony_ci unsigned char reserved[64]; 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistruct snd_pcm_sw_params32 { 718c2ecf20Sopenharmony_ci s32 tstamp_mode; 728c2ecf20Sopenharmony_ci u32 period_step; 738c2ecf20Sopenharmony_ci u32 sleep_min; 748c2ecf20Sopenharmony_ci u32 avail_min; 758c2ecf20Sopenharmony_ci u32 xfer_align; 768c2ecf20Sopenharmony_ci u32 start_threshold; 778c2ecf20Sopenharmony_ci u32 stop_threshold; 788c2ecf20Sopenharmony_ci u32 silence_threshold; 798c2ecf20Sopenharmony_ci u32 silence_size; 808c2ecf20Sopenharmony_ci u32 boundary; 818c2ecf20Sopenharmony_ci u32 proto; 828c2ecf20Sopenharmony_ci u32 tstamp_type; 838c2ecf20Sopenharmony_ci unsigned char reserved[56]; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, 878c2ecf20Sopenharmony_ci struct snd_pcm_sw_params32 __user *src) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct snd_pcm_sw_params params; 908c2ecf20Sopenharmony_ci snd_pcm_uframes_t boundary; 918c2ecf20Sopenharmony_ci int err; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci memset(¶ms, 0, sizeof(params)); 948c2ecf20Sopenharmony_ci if (get_user(params.tstamp_mode, &src->tstamp_mode) || 958c2ecf20Sopenharmony_ci get_user(params.period_step, &src->period_step) || 968c2ecf20Sopenharmony_ci get_user(params.sleep_min, &src->sleep_min) || 978c2ecf20Sopenharmony_ci get_user(params.avail_min, &src->avail_min) || 988c2ecf20Sopenharmony_ci get_user(params.xfer_align, &src->xfer_align) || 998c2ecf20Sopenharmony_ci get_user(params.start_threshold, &src->start_threshold) || 1008c2ecf20Sopenharmony_ci get_user(params.stop_threshold, &src->stop_threshold) || 1018c2ecf20Sopenharmony_ci get_user(params.silence_threshold, &src->silence_threshold) || 1028c2ecf20Sopenharmony_ci get_user(params.silence_size, &src->silence_size) || 1038c2ecf20Sopenharmony_ci get_user(params.tstamp_type, &src->tstamp_type) || 1048c2ecf20Sopenharmony_ci get_user(params.proto, &src->proto)) 1058c2ecf20Sopenharmony_ci return -EFAULT; 1068c2ecf20Sopenharmony_ci /* 1078c2ecf20Sopenharmony_ci * Check silent_size parameter. Since we have 64bit boundary, 1088c2ecf20Sopenharmony_ci * silence_size must be compared with the 32bit boundary. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci boundary = recalculate_boundary(substream->runtime); 1118c2ecf20Sopenharmony_ci if (boundary && params.silence_size >= boundary) 1128c2ecf20Sopenharmony_ci params.silence_size = substream->runtime->boundary; 1138c2ecf20Sopenharmony_ci err = snd_pcm_sw_params(substream, ¶ms); 1148c2ecf20Sopenharmony_ci if (err < 0) 1158c2ecf20Sopenharmony_ci return err; 1168c2ecf20Sopenharmony_ci if (boundary && put_user(boundary, &src->boundary)) 1178c2ecf20Sopenharmony_ci return -EFAULT; 1188c2ecf20Sopenharmony_ci return err; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistruct snd_pcm_channel_info32 { 1228c2ecf20Sopenharmony_ci u32 channel; 1238c2ecf20Sopenharmony_ci u32 offset; 1248c2ecf20Sopenharmony_ci u32 first; 1258c2ecf20Sopenharmony_ci u32 step; 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream, 1298c2ecf20Sopenharmony_ci struct snd_pcm_channel_info32 __user *src) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct snd_pcm_channel_info info; 1328c2ecf20Sopenharmony_ci int err; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (get_user(info.channel, &src->channel) || 1358c2ecf20Sopenharmony_ci get_user(info.offset, &src->offset) || 1368c2ecf20Sopenharmony_ci get_user(info.first, &src->first) || 1378c2ecf20Sopenharmony_ci get_user(info.step, &src->step)) 1388c2ecf20Sopenharmony_ci return -EFAULT; 1398c2ecf20Sopenharmony_ci err = snd_pcm_channel_info(substream, &info); 1408c2ecf20Sopenharmony_ci if (err < 0) 1418c2ecf20Sopenharmony_ci return err; 1428c2ecf20Sopenharmony_ci if (put_user(info.channel, &src->channel) || 1438c2ecf20Sopenharmony_ci put_user(info.offset, &src->offset) || 1448c2ecf20Sopenharmony_ci put_user(info.first, &src->first) || 1458c2ecf20Sopenharmony_ci put_user(info.step, &src->step)) 1468c2ecf20Sopenharmony_ci return -EFAULT; 1478c2ecf20Sopenharmony_ci return err; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32 1518c2ecf20Sopenharmony_ci/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */ 1528c2ecf20Sopenharmony_cistatic int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, 1538c2ecf20Sopenharmony_ci struct snd_pcm_channel_info __user *src); 1548c2ecf20Sopenharmony_ci#define snd_pcm_ioctl_channel_info_x32(s, p) \ 1558c2ecf20Sopenharmony_ci snd_pcm_channel_info_user(s, p) 1568c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_X32 */ 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistruct compat_snd_pcm_status64 { 1598c2ecf20Sopenharmony_ci snd_pcm_state_t state; 1608c2ecf20Sopenharmony_ci u8 rsvd[4]; /* alignment */ 1618c2ecf20Sopenharmony_ci s64 trigger_tstamp_sec; 1628c2ecf20Sopenharmony_ci s64 trigger_tstamp_nsec; 1638c2ecf20Sopenharmony_ci s64 tstamp_sec; 1648c2ecf20Sopenharmony_ci s64 tstamp_nsec; 1658c2ecf20Sopenharmony_ci u32 appl_ptr; 1668c2ecf20Sopenharmony_ci u32 hw_ptr; 1678c2ecf20Sopenharmony_ci s32 delay; 1688c2ecf20Sopenharmony_ci u32 avail; 1698c2ecf20Sopenharmony_ci u32 avail_max; 1708c2ecf20Sopenharmony_ci u32 overrange; 1718c2ecf20Sopenharmony_ci snd_pcm_state_t suspended_state; 1728c2ecf20Sopenharmony_ci u32 audio_tstamp_data; 1738c2ecf20Sopenharmony_ci s64 audio_tstamp_sec; 1748c2ecf20Sopenharmony_ci s64 audio_tstamp_nsec; 1758c2ecf20Sopenharmony_ci s64 driver_tstamp_sec; 1768c2ecf20Sopenharmony_ci s64 driver_tstamp_nsec; 1778c2ecf20Sopenharmony_ci u32 audio_tstamp_accuracy; 1788c2ecf20Sopenharmony_ci unsigned char reserved[52-4*sizeof(s64)]; 1798c2ecf20Sopenharmony_ci} __packed; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream, 1828c2ecf20Sopenharmony_ci struct compat_snd_pcm_status64 __user *src, 1838c2ecf20Sopenharmony_ci bool ext) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct snd_pcm_status64 status; 1868c2ecf20Sopenharmony_ci struct compat_snd_pcm_status64 compat_status64; 1878c2ecf20Sopenharmony_ci int err; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci memset(&status, 0, sizeof(status)); 1908c2ecf20Sopenharmony_ci memset(&compat_status64, 0, sizeof(compat_status64)); 1918c2ecf20Sopenharmony_ci /* 1928c2ecf20Sopenharmony_ci * with extension, parameters are read/write, 1938c2ecf20Sopenharmony_ci * get audio_tstamp_data from user, 1948c2ecf20Sopenharmony_ci * ignore rest of status structure 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_ci if (ext && get_user(status.audio_tstamp_data, 1978c2ecf20Sopenharmony_ci (u32 __user *)(&src->audio_tstamp_data))) 1988c2ecf20Sopenharmony_ci return -EFAULT; 1998c2ecf20Sopenharmony_ci err = snd_pcm_status64(substream, &status); 2008c2ecf20Sopenharmony_ci if (err < 0) 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (clear_user(src, sizeof(*src))) 2048c2ecf20Sopenharmony_ci return -EFAULT; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci compat_status64 = (struct compat_snd_pcm_status64) { 2078c2ecf20Sopenharmony_ci .state = status.state, 2088c2ecf20Sopenharmony_ci .trigger_tstamp_sec = status.trigger_tstamp_sec, 2098c2ecf20Sopenharmony_ci .trigger_tstamp_nsec = status.trigger_tstamp_nsec, 2108c2ecf20Sopenharmony_ci .tstamp_sec = status.tstamp_sec, 2118c2ecf20Sopenharmony_ci .tstamp_nsec = status.tstamp_nsec, 2128c2ecf20Sopenharmony_ci .appl_ptr = status.appl_ptr, 2138c2ecf20Sopenharmony_ci .hw_ptr = status.hw_ptr, 2148c2ecf20Sopenharmony_ci .delay = status.delay, 2158c2ecf20Sopenharmony_ci .avail = status.avail, 2168c2ecf20Sopenharmony_ci .avail_max = status.avail_max, 2178c2ecf20Sopenharmony_ci .overrange = status.overrange, 2188c2ecf20Sopenharmony_ci .suspended_state = status.suspended_state, 2198c2ecf20Sopenharmony_ci .audio_tstamp_data = status.audio_tstamp_data, 2208c2ecf20Sopenharmony_ci .audio_tstamp_sec = status.audio_tstamp_sec, 2218c2ecf20Sopenharmony_ci .audio_tstamp_nsec = status.audio_tstamp_nsec, 2228c2ecf20Sopenharmony_ci .driver_tstamp_sec = status.audio_tstamp_sec, 2238c2ecf20Sopenharmony_ci .driver_tstamp_nsec = status.audio_tstamp_nsec, 2248c2ecf20Sopenharmony_ci .audio_tstamp_accuracy = status.audio_tstamp_accuracy, 2258c2ecf20Sopenharmony_ci }; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (copy_to_user(src, &compat_status64, sizeof(compat_status64))) 2288c2ecf20Sopenharmony_ci return -EFAULT; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci return err; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/* both for HW_PARAMS and HW_REFINE */ 2348c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, 2358c2ecf20Sopenharmony_ci int refine, 2368c2ecf20Sopenharmony_ci struct snd_pcm_hw_params32 __user *data32) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *data; 2398c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime; 2408c2ecf20Sopenharmony_ci int err; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (! (runtime = substream->runtime)) 2438c2ecf20Sopenharmony_ci return -ENOTTY; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci data = kmalloc(sizeof(*data), GFP_KERNEL); 2468c2ecf20Sopenharmony_ci if (!data) 2478c2ecf20Sopenharmony_ci return -ENOMEM; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* only fifo_size (RO from userspace) is different, so just copy all */ 2508c2ecf20Sopenharmony_ci if (copy_from_user(data, data32, sizeof(*data32))) { 2518c2ecf20Sopenharmony_ci err = -EFAULT; 2528c2ecf20Sopenharmony_ci goto error; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (refine) { 2568c2ecf20Sopenharmony_ci err = snd_pcm_hw_refine(substream, data); 2578c2ecf20Sopenharmony_ci if (err < 0) 2588c2ecf20Sopenharmony_ci goto error; 2598c2ecf20Sopenharmony_ci err = fixup_unreferenced_params(substream, data); 2608c2ecf20Sopenharmony_ci } else { 2618c2ecf20Sopenharmony_ci err = snd_pcm_hw_params(substream, data); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci if (err < 0) 2648c2ecf20Sopenharmony_ci goto error; 2658c2ecf20Sopenharmony_ci if (copy_to_user(data32, data, sizeof(*data32)) || 2668c2ecf20Sopenharmony_ci put_user(data->fifo_size, &data32->fifo_size)) { 2678c2ecf20Sopenharmony_ci err = -EFAULT; 2688c2ecf20Sopenharmony_ci goto error; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (! refine) { 2728c2ecf20Sopenharmony_ci unsigned int new_boundary = recalculate_boundary(runtime); 2738c2ecf20Sopenharmony_ci if (new_boundary) 2748c2ecf20Sopenharmony_ci runtime->boundary = new_boundary; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci error: 2778c2ecf20Sopenharmony_ci kfree(data); 2788c2ecf20Sopenharmony_ci return err; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/* 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_cistruct snd_xferi32 { 2858c2ecf20Sopenharmony_ci s32 result; 2868c2ecf20Sopenharmony_ci u32 buf; 2878c2ecf20Sopenharmony_ci u32 frames; 2888c2ecf20Sopenharmony_ci}; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, 2918c2ecf20Sopenharmony_ci int dir, struct snd_xferi32 __user *data32) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci compat_caddr_t buf; 2948c2ecf20Sopenharmony_ci u32 frames; 2958c2ecf20Sopenharmony_ci int err; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (! substream->runtime) 2988c2ecf20Sopenharmony_ci return -ENOTTY; 2998c2ecf20Sopenharmony_ci if (substream->stream != dir) 3008c2ecf20Sopenharmony_ci return -EINVAL; 3018c2ecf20Sopenharmony_ci if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) 3028c2ecf20Sopenharmony_ci return -EBADFD; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (get_user(buf, &data32->buf) || 3058c2ecf20Sopenharmony_ci get_user(frames, &data32->frames)) 3068c2ecf20Sopenharmony_ci return -EFAULT; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (dir == SNDRV_PCM_STREAM_PLAYBACK) 3098c2ecf20Sopenharmony_ci err = snd_pcm_lib_write(substream, compat_ptr(buf), frames); 3108c2ecf20Sopenharmony_ci else 3118c2ecf20Sopenharmony_ci err = snd_pcm_lib_read(substream, compat_ptr(buf), frames); 3128c2ecf20Sopenharmony_ci if (err < 0) 3138c2ecf20Sopenharmony_ci return err; 3148c2ecf20Sopenharmony_ci /* copy the result */ 3158c2ecf20Sopenharmony_ci if (put_user(err, &data32->result)) 3168c2ecf20Sopenharmony_ci return -EFAULT; 3178c2ecf20Sopenharmony_ci return 0; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci/* snd_xfern needs remapping of bufs */ 3228c2ecf20Sopenharmony_cistruct snd_xfern32 { 3238c2ecf20Sopenharmony_ci s32 result; 3248c2ecf20Sopenharmony_ci u32 bufs; /* this is void **; */ 3258c2ecf20Sopenharmony_ci u32 frames; 3268c2ecf20Sopenharmony_ci}; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* 3298c2ecf20Sopenharmony_ci * xfern ioctl nees to copy (up to) 128 pointers on stack. 3308c2ecf20Sopenharmony_ci * although we may pass the copied pointers through f_op->ioctl, but the ioctl 3318c2ecf20Sopenharmony_ci * handler there expands again the same 128 pointers on stack, so it is better 3328c2ecf20Sopenharmony_ci * to handle the function (calling pcm_readv/writev) directly in this handler. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, 3358c2ecf20Sopenharmony_ci int dir, struct snd_xfern32 __user *data32) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci compat_caddr_t buf; 3388c2ecf20Sopenharmony_ci compat_caddr_t __user *bufptr; 3398c2ecf20Sopenharmony_ci u32 frames; 3408c2ecf20Sopenharmony_ci void __user **bufs; 3418c2ecf20Sopenharmony_ci int err, ch, i; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (! substream->runtime) 3448c2ecf20Sopenharmony_ci return -ENOTTY; 3458c2ecf20Sopenharmony_ci if (substream->stream != dir) 3468c2ecf20Sopenharmony_ci return -EINVAL; 3478c2ecf20Sopenharmony_ci if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) 3488c2ecf20Sopenharmony_ci return -EBADFD; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if ((ch = substream->runtime->channels) > 128) 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci if (get_user(buf, &data32->bufs) || 3538c2ecf20Sopenharmony_ci get_user(frames, &data32->frames)) 3548c2ecf20Sopenharmony_ci return -EFAULT; 3558c2ecf20Sopenharmony_ci bufptr = compat_ptr(buf); 3568c2ecf20Sopenharmony_ci bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL); 3578c2ecf20Sopenharmony_ci if (bufs == NULL) 3588c2ecf20Sopenharmony_ci return -ENOMEM; 3598c2ecf20Sopenharmony_ci for (i = 0; i < ch; i++) { 3608c2ecf20Sopenharmony_ci u32 ptr; 3618c2ecf20Sopenharmony_ci if (get_user(ptr, bufptr)) { 3628c2ecf20Sopenharmony_ci kfree(bufs); 3638c2ecf20Sopenharmony_ci return -EFAULT; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci bufs[i] = compat_ptr(ptr); 3668c2ecf20Sopenharmony_ci bufptr++; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci if (dir == SNDRV_PCM_STREAM_PLAYBACK) 3698c2ecf20Sopenharmony_ci err = snd_pcm_lib_writev(substream, bufs, frames); 3708c2ecf20Sopenharmony_ci else 3718c2ecf20Sopenharmony_ci err = snd_pcm_lib_readv(substream, bufs, frames); 3728c2ecf20Sopenharmony_ci if (err >= 0) { 3738c2ecf20Sopenharmony_ci if (put_user(err, &data32->result)) 3748c2ecf20Sopenharmony_ci err = -EFAULT; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci kfree(bufs); 3778c2ecf20Sopenharmony_ci return err; 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32 3818c2ecf20Sopenharmony_ci/* X32 ABI has 64bit timespec and 64bit alignment */ 3828c2ecf20Sopenharmony_cistruct snd_pcm_mmap_status_x32 { 3838c2ecf20Sopenharmony_ci snd_pcm_state_t state; 3848c2ecf20Sopenharmony_ci s32 pad1; 3858c2ecf20Sopenharmony_ci u32 hw_ptr; 3868c2ecf20Sopenharmony_ci u32 pad2; /* alignment */ 3878c2ecf20Sopenharmony_ci s64 tstamp_sec; 3888c2ecf20Sopenharmony_ci s64 tstamp_nsec; 3898c2ecf20Sopenharmony_ci snd_pcm_state_t suspended_state; 3908c2ecf20Sopenharmony_ci s32 pad3; 3918c2ecf20Sopenharmony_ci s64 audio_tstamp_sec; 3928c2ecf20Sopenharmony_ci s64 audio_tstamp_nsec; 3938c2ecf20Sopenharmony_ci} __packed; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistruct snd_pcm_mmap_control_x32 { 3968c2ecf20Sopenharmony_ci u32 appl_ptr; 3978c2ecf20Sopenharmony_ci u32 avail_min; 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistruct snd_pcm_sync_ptr_x32 { 4018c2ecf20Sopenharmony_ci u32 flags; 4028c2ecf20Sopenharmony_ci u32 rsvd; /* alignment */ 4038c2ecf20Sopenharmony_ci union { 4048c2ecf20Sopenharmony_ci struct snd_pcm_mmap_status_x32 status; 4058c2ecf20Sopenharmony_ci unsigned char reserved[64]; 4068c2ecf20Sopenharmony_ci } s; 4078c2ecf20Sopenharmony_ci union { 4088c2ecf20Sopenharmony_ci struct snd_pcm_mmap_control_x32 control; 4098c2ecf20Sopenharmony_ci unsigned char reserved[64]; 4108c2ecf20Sopenharmony_ci } c; 4118c2ecf20Sopenharmony_ci} __packed; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream, 4148c2ecf20Sopenharmony_ci struct snd_pcm_sync_ptr_x32 __user *src) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 4178c2ecf20Sopenharmony_ci volatile struct snd_pcm_mmap_status *status; 4188c2ecf20Sopenharmony_ci volatile struct snd_pcm_mmap_control *control; 4198c2ecf20Sopenharmony_ci u32 sflags; 4208c2ecf20Sopenharmony_ci struct snd_pcm_mmap_control scontrol; 4218c2ecf20Sopenharmony_ci struct snd_pcm_mmap_status sstatus; 4228c2ecf20Sopenharmony_ci snd_pcm_uframes_t boundary; 4238c2ecf20Sopenharmony_ci int err; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (snd_BUG_ON(!runtime)) 4268c2ecf20Sopenharmony_ci return -EINVAL; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (get_user(sflags, &src->flags) || 4298c2ecf20Sopenharmony_ci get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || 4308c2ecf20Sopenharmony_ci get_user(scontrol.avail_min, &src->c.control.avail_min)) 4318c2ecf20Sopenharmony_ci return -EFAULT; 4328c2ecf20Sopenharmony_ci if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { 4338c2ecf20Sopenharmony_ci err = snd_pcm_hwsync(substream); 4348c2ecf20Sopenharmony_ci if (err < 0) 4358c2ecf20Sopenharmony_ci return err; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci status = runtime->status; 4388c2ecf20Sopenharmony_ci control = runtime->control; 4398c2ecf20Sopenharmony_ci boundary = recalculate_boundary(runtime); 4408c2ecf20Sopenharmony_ci if (!boundary) 4418c2ecf20Sopenharmony_ci boundary = 0x7fffffff; 4428c2ecf20Sopenharmony_ci snd_pcm_stream_lock_irq(substream); 4438c2ecf20Sopenharmony_ci /* FIXME: we should consider the boundary for the sync from app */ 4448c2ecf20Sopenharmony_ci if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) 4458c2ecf20Sopenharmony_ci control->appl_ptr = scontrol.appl_ptr; 4468c2ecf20Sopenharmony_ci else 4478c2ecf20Sopenharmony_ci scontrol.appl_ptr = control->appl_ptr % boundary; 4488c2ecf20Sopenharmony_ci if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 4498c2ecf20Sopenharmony_ci control->avail_min = scontrol.avail_min; 4508c2ecf20Sopenharmony_ci else 4518c2ecf20Sopenharmony_ci scontrol.avail_min = control->avail_min; 4528c2ecf20Sopenharmony_ci sstatus.state = status->state; 4538c2ecf20Sopenharmony_ci sstatus.hw_ptr = status->hw_ptr % boundary; 4548c2ecf20Sopenharmony_ci sstatus.tstamp = status->tstamp; 4558c2ecf20Sopenharmony_ci sstatus.suspended_state = status->suspended_state; 4568c2ecf20Sopenharmony_ci sstatus.audio_tstamp = status->audio_tstamp; 4578c2ecf20Sopenharmony_ci snd_pcm_stream_unlock_irq(substream); 4588c2ecf20Sopenharmony_ci if (put_user(sstatus.state, &src->s.status.state) || 4598c2ecf20Sopenharmony_ci put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || 4608c2ecf20Sopenharmony_ci put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) || 4618c2ecf20Sopenharmony_ci put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) || 4628c2ecf20Sopenharmony_ci put_user(sstatus.suspended_state, &src->s.status.suspended_state) || 4638c2ecf20Sopenharmony_ci put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) || 4648c2ecf20Sopenharmony_ci put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) || 4658c2ecf20Sopenharmony_ci put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || 4668c2ecf20Sopenharmony_ci put_user(scontrol.avail_min, &src->c.control.avail_min)) 4678c2ecf20Sopenharmony_ci return -EFAULT; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return 0; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_X32 */ 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 4748c2ecf20Sopenharmony_citypedef char __pad_before_u32[4]; 4758c2ecf20Sopenharmony_citypedef char __pad_after_u32[0]; 4768c2ecf20Sopenharmony_ci#else 4778c2ecf20Sopenharmony_citypedef char __pad_before_u32[0]; 4788c2ecf20Sopenharmony_citypedef char __pad_after_u32[4]; 4798c2ecf20Sopenharmony_ci#endif 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci/* PCM 2.0.15 API definition had a bug in mmap control; it puts the avail_min 4828c2ecf20Sopenharmony_ci * at the wrong offset due to a typo in padding type. 4838c2ecf20Sopenharmony_ci * The bug hits only 32bit. 4848c2ecf20Sopenharmony_ci * A workaround for incorrect read/write is needed only in 32bit compat mode. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_cistruct __snd_pcm_mmap_control64_buggy { 4878c2ecf20Sopenharmony_ci __pad_before_u32 __pad1; 4888c2ecf20Sopenharmony_ci __u32 appl_ptr; 4898c2ecf20Sopenharmony_ci __pad_before_u32 __pad2; /* SiC! here is the bug */ 4908c2ecf20Sopenharmony_ci __pad_before_u32 __pad3; 4918c2ecf20Sopenharmony_ci __u32 avail_min; 4928c2ecf20Sopenharmony_ci __pad_after_uframe __pad4; 4938c2ecf20Sopenharmony_ci}; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream, 4968c2ecf20Sopenharmony_ci struct snd_pcm_sync_ptr __user *_sync_ptr) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 4998c2ecf20Sopenharmony_ci struct snd_pcm_sync_ptr sync_ptr; 5008c2ecf20Sopenharmony_ci struct __snd_pcm_mmap_control64_buggy *sync_cp; 5018c2ecf20Sopenharmony_ci volatile struct snd_pcm_mmap_status *status; 5028c2ecf20Sopenharmony_ci volatile struct snd_pcm_mmap_control *control; 5038c2ecf20Sopenharmony_ci int err; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci memset(&sync_ptr, 0, sizeof(sync_ptr)); 5068c2ecf20Sopenharmony_ci sync_cp = (struct __snd_pcm_mmap_control64_buggy *)&sync_ptr.c.control; 5078c2ecf20Sopenharmony_ci if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) 5088c2ecf20Sopenharmony_ci return -EFAULT; 5098c2ecf20Sopenharmony_ci if (copy_from_user(sync_cp, &(_sync_ptr->c.control), sizeof(*sync_cp))) 5108c2ecf20Sopenharmony_ci return -EFAULT; 5118c2ecf20Sopenharmony_ci status = runtime->status; 5128c2ecf20Sopenharmony_ci control = runtime->control; 5138c2ecf20Sopenharmony_ci if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { 5148c2ecf20Sopenharmony_ci err = snd_pcm_hwsync(substream); 5158c2ecf20Sopenharmony_ci if (err < 0) 5168c2ecf20Sopenharmony_ci return err; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci snd_pcm_stream_lock_irq(substream); 5198c2ecf20Sopenharmony_ci if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { 5208c2ecf20Sopenharmony_ci err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr); 5218c2ecf20Sopenharmony_ci if (err < 0) { 5228c2ecf20Sopenharmony_ci snd_pcm_stream_unlock_irq(substream); 5238c2ecf20Sopenharmony_ci return err; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci } else { 5268c2ecf20Sopenharmony_ci sync_cp->appl_ptr = control->appl_ptr; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) 5298c2ecf20Sopenharmony_ci control->avail_min = sync_cp->avail_min; 5308c2ecf20Sopenharmony_ci else 5318c2ecf20Sopenharmony_ci sync_cp->avail_min = control->avail_min; 5328c2ecf20Sopenharmony_ci sync_ptr.s.status.state = status->state; 5338c2ecf20Sopenharmony_ci sync_ptr.s.status.hw_ptr = status->hw_ptr; 5348c2ecf20Sopenharmony_ci sync_ptr.s.status.tstamp = status->tstamp; 5358c2ecf20Sopenharmony_ci sync_ptr.s.status.suspended_state = status->suspended_state; 5368c2ecf20Sopenharmony_ci sync_ptr.s.status.audio_tstamp = status->audio_tstamp; 5378c2ecf20Sopenharmony_ci snd_pcm_stream_unlock_irq(substream); 5388c2ecf20Sopenharmony_ci if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) 5398c2ecf20Sopenharmony_ci return -EFAULT; 5408c2ecf20Sopenharmony_ci return 0; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci/* 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_cienum { 5468c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32), 5478c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), 5488c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), 5498c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32), 5508c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32), 5518c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), 5528c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), 5538c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), 5548c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), 5558c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32), 5568c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32), 5578c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), 5588c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), 5598c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64), 5608c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64), 5618c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32 5628c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), 5638c2ecf20Sopenharmony_ci SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), 5648c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_X32 */ 5658c2ecf20Sopenharmony_ci}; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct snd_pcm_file *pcm_file; 5708c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream; 5718c2ecf20Sopenharmony_ci void __user *argp = compat_ptr(arg); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci pcm_file = file->private_data; 5748c2ecf20Sopenharmony_ci if (! pcm_file) 5758c2ecf20Sopenharmony_ci return -ENOTTY; 5768c2ecf20Sopenharmony_ci substream = pcm_file->substream; 5778c2ecf20Sopenharmony_ci if (! substream) 5788c2ecf20Sopenharmony_ci return -ENOTTY; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* 5818c2ecf20Sopenharmony_ci * When PCM is used on 32bit mode, we need to disable 5828c2ecf20Sopenharmony_ci * mmap of the old PCM status/control records because 5838c2ecf20Sopenharmony_ci * of the size incompatibility. 5848c2ecf20Sopenharmony_ci */ 5858c2ecf20Sopenharmony_ci pcm_file->no_compat_mmap = 1; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci switch (cmd) { 5888c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_PVERSION: 5898c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_INFO: 5908c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_TSTAMP: 5918c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_TTSTAMP: 5928c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_USER_PVERSION: 5938c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_HWSYNC: 5948c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_PREPARE: 5958c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_RESET: 5968c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_START: 5978c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_DROP: 5988c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_DRAIN: 5998c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_PAUSE: 6008c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_HW_FREE: 6018c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_RESUME: 6028c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_XRUN: 6038c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_LINK: 6048c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_UNLINK: 6058c2ecf20Sopenharmony_ci case __SNDRV_PCM_IOCTL_SYNC_PTR32: 6068c2ecf20Sopenharmony_ci return snd_pcm_common_ioctl(file, substream, cmd, argp); 6078c2ecf20Sopenharmony_ci case __SNDRV_PCM_IOCTL_SYNC_PTR64: 6088c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32 6098c2ecf20Sopenharmony_ci if (in_x32_syscall()) 6108c2ecf20Sopenharmony_ci return snd_pcm_ioctl_sync_ptr_x32(substream, argp); 6118c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_X32 */ 6128c2ecf20Sopenharmony_ci return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); 6138c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_HW_REFINE32: 6148c2ecf20Sopenharmony_ci return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); 6158c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_HW_PARAMS32: 6168c2ecf20Sopenharmony_ci return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); 6178c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_SW_PARAMS32: 6188c2ecf20Sopenharmony_ci return snd_pcm_ioctl_sw_params_compat(substream, argp); 6198c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_STATUS_COMPAT32: 6208c2ecf20Sopenharmony_ci return snd_pcm_status_user32(substream, argp, false); 6218c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32: 6228c2ecf20Sopenharmony_ci return snd_pcm_status_user32(substream, argp, true); 6238c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_CHANNEL_INFO32: 6248c2ecf20Sopenharmony_ci return snd_pcm_ioctl_channel_info_compat(substream, argp); 6258c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: 6268c2ecf20Sopenharmony_ci return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); 6278c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_READI_FRAMES32: 6288c2ecf20Sopenharmony_ci return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); 6298c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_WRITEN_FRAMES32: 6308c2ecf20Sopenharmony_ci return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); 6318c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_READN_FRAMES32: 6328c2ecf20Sopenharmony_ci return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); 6338c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_DELAY32: 6348c2ecf20Sopenharmony_ci return snd_pcm_ioctl_delay_compat(substream, argp); 6358c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_REWIND32: 6368c2ecf20Sopenharmony_ci return snd_pcm_ioctl_rewind_compat(substream, argp); 6378c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_FORWARD32: 6388c2ecf20Sopenharmony_ci return snd_pcm_ioctl_forward_compat(substream, argp); 6398c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_STATUS_COMPAT64: 6408c2ecf20Sopenharmony_ci return snd_pcm_status_user_compat64(substream, argp, false); 6418c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: 6428c2ecf20Sopenharmony_ci return snd_pcm_status_user_compat64(substream, argp, true); 6438c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32 6448c2ecf20Sopenharmony_ci case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: 6458c2ecf20Sopenharmony_ci return snd_pcm_ioctl_channel_info_x32(substream, argp); 6468c2ecf20Sopenharmony_ci#endif /* CONFIG_X86_X32 */ 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci return -ENOIOCTLCMD; 6508c2ecf20Sopenharmony_ci} 651