18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *   32bit -> 64bit ioctl wrapper for hwdep API
48c2ecf20Sopenharmony_ci *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci/* This file is included from hwdep.c */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/compat.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistruct snd_hwdep_dsp_image32 {
128c2ecf20Sopenharmony_ci	u32 index;
138c2ecf20Sopenharmony_ci	unsigned char name[64];
148c2ecf20Sopenharmony_ci	u32 image;	/* pointer */
158c2ecf20Sopenharmony_ci	u32 length;
168c2ecf20Sopenharmony_ci	u32 driver_data;
178c2ecf20Sopenharmony_ci} /* don't set packed attribute here */;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw,
208c2ecf20Sopenharmony_ci				     struct snd_hwdep_dsp_image32 __user *src)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct snd_hwdep_dsp_image info = {};
238c2ecf20Sopenharmony_ci	compat_caddr_t ptr;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	if (copy_from_user(&info, src, 4 + 64) ||
268c2ecf20Sopenharmony_ci	    get_user(ptr, &src->image) ||
278c2ecf20Sopenharmony_ci	    get_user(info.length, &src->length) ||
288c2ecf20Sopenharmony_ci	    get_user(info.driver_data, &src->driver_data))
298c2ecf20Sopenharmony_ci		return -EFAULT;
308c2ecf20Sopenharmony_ci	info.image = compat_ptr(ptr);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	return snd_hwdep_dsp_load(hw, &info);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cienum {
368c2ecf20Sopenharmony_ci	SNDRV_HWDEP_IOCTL_DSP_LOAD32   = _IOW('H', 0x03, struct snd_hwdep_dsp_image32)
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd,
408c2ecf20Sopenharmony_ci				   unsigned long arg)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	struct snd_hwdep *hw = file->private_data;
438c2ecf20Sopenharmony_ci	void __user *argp = compat_ptr(arg);
448c2ecf20Sopenharmony_ci	switch (cmd) {
458c2ecf20Sopenharmony_ci	case SNDRV_HWDEP_IOCTL_PVERSION:
468c2ecf20Sopenharmony_ci	case SNDRV_HWDEP_IOCTL_INFO:
478c2ecf20Sopenharmony_ci	case SNDRV_HWDEP_IOCTL_DSP_STATUS:
488c2ecf20Sopenharmony_ci		return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
498c2ecf20Sopenharmony_ci	case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
508c2ecf20Sopenharmony_ci		return snd_hwdep_dsp_load_compat(hw, argp);
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci	if (hw->ops.ioctl_compat)
538c2ecf20Sopenharmony_ci		return hw->ops.ioctl_compat(hw, file, cmd, arg);
548c2ecf20Sopenharmony_ci	return -ENOIOCTLCMD;
558c2ecf20Sopenharmony_ci}
56