Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * 32bit -> 64bit ioctl wrapper for timer API
4 : : * 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 size
13 : : * of storage alignment differs depending on architectures. Here, '__packed'
14 : : * qualifier is used so that the size of this structure is multiple of 4 and
15 : : * it fits to any architectures with 32 bit storage alignment.
16 : : */
17 : : struct 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 : :
24 : : struct 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 : :
34 : : static 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 : :
47 : : static 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 : : strlcpy(info.id, t->id, sizeof(info.id));
65 : : strlcpy(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 : :
72 : : enum {
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 : :
79 : 0 : static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
80 : : unsigned long arg)
81 : : {
82 [ # # # # : 0 : void __user *argp = compat_ptr(arg);
# # ]
83 : :
84 [ # # # # : 0 : switch (cmd) {
# # ]
85 : 0 : 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 : 0 : return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp, true);
102 : 0 : case SNDRV_TIMER_IOCTL_GPARAMS32:
103 : 0 : return snd_timer_user_gparams_compat(file, argp);
104 : 0 : case SNDRV_TIMER_IOCTL_INFO32:
105 : 0 : return snd_timer_user_info_compat(file, argp);
106 : 0 : case SNDRV_TIMER_IOCTL_STATUS_COMPAT32:
107 : 0 : return snd_timer_user_status32(file, argp);
108 : 0 : case SNDRV_TIMER_IOCTL_STATUS_COMPAT64:
109 : 0 : return snd_timer_user_status64(file, argp);
110 : : }
111 : : return -ENOIOCTLCMD;
112 : : }
113 : :
114 : 0 : static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
115 : : unsigned long arg)
116 : : {
117 : 0 : struct snd_timer_user *tu = file->private_data;
118 : 0 : long ret;
119 : :
120 : 0 : mutex_lock(&tu->ioctl_lock);
121 : 0 : ret = __snd_timer_user_ioctl_compat(file, cmd, arg);
122 : 0 : mutex_unlock(&tu->ioctl_lock);
123 : 0 : return ret;
124 : : }
|