0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/compat.h>
0010
0011
0012
0013
0014
0015
0016
0017 struct snd_timer_gparams32 {
0018 struct snd_timer_id tid;
0019 u32 period_num;
0020 u32 period_den;
0021 unsigned char reserved[32];
0022 } __packed;
0023
0024 struct snd_timer_info32 {
0025 u32 flags;
0026 s32 card;
0027 unsigned char id[64];
0028 unsigned char name[80];
0029 u32 reserved0;
0030 u32 resolution;
0031 unsigned char reserved[64];
0032 };
0033
0034 static int snd_timer_user_gparams_compat(struct file *file,
0035 struct snd_timer_gparams32 __user *user)
0036 {
0037 struct snd_timer_gparams gparams;
0038
0039 if (copy_from_user(&gparams.tid, &user->tid, sizeof(gparams.tid)) ||
0040 get_user(gparams.period_num, &user->period_num) ||
0041 get_user(gparams.period_den, &user->period_den))
0042 return -EFAULT;
0043
0044 return timer_set_gparams(&gparams);
0045 }
0046
0047 static int snd_timer_user_info_compat(struct file *file,
0048 struct snd_timer_info32 __user *_info)
0049 {
0050 struct snd_timer_user *tu;
0051 struct snd_timer_info32 info;
0052 struct snd_timer *t;
0053
0054 tu = file->private_data;
0055 if (!tu->timeri)
0056 return -EBADFD;
0057 t = tu->timeri->timer;
0058 if (!t)
0059 return -EBADFD;
0060 memset(&info, 0, sizeof(info));
0061 info.card = t->card ? t->card->number : -1;
0062 if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
0063 info.flags |= SNDRV_TIMER_FLG_SLAVE;
0064 strscpy(info.id, t->id, sizeof(info.id));
0065 strscpy(info.name, t->name, sizeof(info.name));
0066 info.resolution = t->hw.resolution;
0067 if (copy_to_user(_info, &info, sizeof(*_info)))
0068 return -EFAULT;
0069 return 0;
0070 }
0071
0072 enum {
0073 SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32),
0074 SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
0075 SNDRV_TIMER_IOCTL_STATUS_COMPAT32 = _IOW('T', 0x14, struct snd_timer_status32),
0076 SNDRV_TIMER_IOCTL_STATUS_COMPAT64 = _IOW('T', 0x14, struct snd_timer_status64),
0077 };
0078
0079 static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
0080 unsigned long arg)
0081 {
0082 void __user *argp = compat_ptr(arg);
0083
0084 switch (cmd) {
0085 case SNDRV_TIMER_IOCTL_PVERSION:
0086 case SNDRV_TIMER_IOCTL_TREAD_OLD:
0087 case SNDRV_TIMER_IOCTL_TREAD64:
0088 case SNDRV_TIMER_IOCTL_GINFO:
0089 case SNDRV_TIMER_IOCTL_GSTATUS:
0090 case SNDRV_TIMER_IOCTL_SELECT:
0091 case SNDRV_TIMER_IOCTL_PARAMS:
0092 case SNDRV_TIMER_IOCTL_START:
0093 case SNDRV_TIMER_IOCTL_START_OLD:
0094 case SNDRV_TIMER_IOCTL_STOP:
0095 case SNDRV_TIMER_IOCTL_STOP_OLD:
0096 case SNDRV_TIMER_IOCTL_CONTINUE:
0097 case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
0098 case SNDRV_TIMER_IOCTL_PAUSE:
0099 case SNDRV_TIMER_IOCTL_PAUSE_OLD:
0100 case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
0101 return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp, true);
0102 case SNDRV_TIMER_IOCTL_GPARAMS32:
0103 return snd_timer_user_gparams_compat(file, argp);
0104 case SNDRV_TIMER_IOCTL_INFO32:
0105 return snd_timer_user_info_compat(file, argp);
0106 case SNDRV_TIMER_IOCTL_STATUS_COMPAT32:
0107 return snd_timer_user_status32(file, argp);
0108 case SNDRV_TIMER_IOCTL_STATUS_COMPAT64:
0109 return snd_timer_user_status64(file, argp);
0110 }
0111 return -ENOIOCTLCMD;
0112 }
0113
0114 static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
0115 unsigned long arg)
0116 {
0117 struct snd_timer_user *tu = file->private_data;
0118 long ret;
0119
0120 mutex_lock(&tu->ioctl_lock);
0121 ret = __snd_timer_user_ioctl_compat(file, cmd, arg);
0122 mutex_unlock(&tu->ioctl_lock);
0123 return ret;
0124 }