122 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * 32bit -> 64bit ioctl wrapper for timer API4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>5 */6 7/* This file included from timer.c */8 9#include <linux/compat.h>10 11/*12 * ILP32/LP64 has different size for 'long' type. Additionally, the size13 * of storage alignment differs depending on architectures. Here, '__packed'14 * qualifier is used so that the size of this structure is multiple of 4 and15 * it fits to any architectures with 32 bit storage alignment.16 */17struct snd_timer_gparams32 {18 struct snd_timer_id tid;19 u32 period_num;20 u32 period_den;21 unsigned char reserved[32];22} __packed;23 24struct snd_timer_info32 {25 u32 flags;26 s32 card;27 unsigned char id[64];28 unsigned char name[80];29 u32 reserved0;30 u32 resolution;31 unsigned char reserved[64];32};33 34static int snd_timer_user_gparams_compat(struct file *file,35 struct snd_timer_gparams32 __user *user)36{37 struct snd_timer_gparams gparams;38 39 if (copy_from_user(&gparams.tid, &user->tid, sizeof(gparams.tid)) ||40 get_user(gparams.period_num, &user->period_num) ||41 get_user(gparams.period_den, &user->period_den))42 return -EFAULT;43 44 return timer_set_gparams(&gparams);45}46 47static int snd_timer_user_info_compat(struct file *file,48 struct snd_timer_info32 __user *_info)49{50 struct snd_timer_user *tu;51 struct snd_timer_info32 info;52 struct snd_timer *t;53 54 tu = file->private_data;55 if (!tu->timeri)56 return -EBADFD;57 t = tu->timeri->timer;58 if (!t)59 return -EBADFD;60 memset(&info, 0, sizeof(info));61 info.card = t->card ? t->card->number : -1;62 if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)63 info.flags |= SNDRV_TIMER_FLG_SLAVE;64 strscpy(info.id, t->id, sizeof(info.id));65 strscpy(info.name, t->name, sizeof(info.name));66 info.resolution = t->hw.resolution;67 if (copy_to_user(_info, &info, sizeof(*_info)))68 return -EFAULT;69 return 0;70}71 72enum {73 SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32),74 SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),75 SNDRV_TIMER_IOCTL_STATUS_COMPAT32 = _IOW('T', 0x14, struct snd_timer_status32),76 SNDRV_TIMER_IOCTL_STATUS_COMPAT64 = _IOW('T', 0x14, struct snd_timer_status64),77};78 79static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,80 unsigned long arg)81{82 void __user *argp = compat_ptr(arg);83 84 switch (cmd) {85 case SNDRV_TIMER_IOCTL_PVERSION:86 case SNDRV_TIMER_IOCTL_TREAD_OLD:87 case SNDRV_TIMER_IOCTL_TREAD64:88 case SNDRV_TIMER_IOCTL_GINFO:89 case SNDRV_TIMER_IOCTL_GSTATUS:90 case SNDRV_TIMER_IOCTL_SELECT:91 case SNDRV_TIMER_IOCTL_PARAMS:92 case SNDRV_TIMER_IOCTL_START:93 case SNDRV_TIMER_IOCTL_START_OLD:94 case SNDRV_TIMER_IOCTL_STOP:95 case SNDRV_TIMER_IOCTL_STOP_OLD:96 case SNDRV_TIMER_IOCTL_CONTINUE:97 case SNDRV_TIMER_IOCTL_CONTINUE_OLD:98 case SNDRV_TIMER_IOCTL_PAUSE:99 case SNDRV_TIMER_IOCTL_PAUSE_OLD:100 case SNDRV_TIMER_IOCTL_NEXT_DEVICE:101 return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp, true);102 case SNDRV_TIMER_IOCTL_GPARAMS32:103 return snd_timer_user_gparams_compat(file, argp);104 case SNDRV_TIMER_IOCTL_INFO32:105 return snd_timer_user_info_compat(file, argp);106 case SNDRV_TIMER_IOCTL_STATUS_COMPAT32:107 return snd_timer_user_status32(file, argp);108 case SNDRV_TIMER_IOCTL_STATUS_COMPAT64:109 return snd_timer_user_status64(file, argp);110 }111 return -ENOIOCTLCMD;112}113 114static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,115 unsigned long arg)116{117 struct snd_timer_user *tu = file->private_data;118 119 guard(mutex)(&tu->ioctl_lock);120 return __snd_timer_user_ioctl_compat(file, cmd, arg);121}122