Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * 32bit -> 64bit ioctl wrapper for timer API | |
4 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | |
1da177e4 LT |
5 | */ |
6 | ||
7 | /* This file included from timer.c */ | |
8 | ||
9 | #include <linux/compat.h> | |
10 | ||
91d2178e TS |
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 | ||
53d2f744 | 24 | struct snd_timer_info32 { |
1da177e4 LT |
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 | ||
91d2178e TS |
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 | ||
1da177e4 | 47 | static int snd_timer_user_info_compat(struct file *file, |
53d2f744 | 48 | struct snd_timer_info32 __user *_info) |
1da177e4 | 49 | { |
53d2f744 TI |
50 | struct snd_timer_user *tu; |
51 | struct snd_timer_info32 info; | |
52 | struct snd_timer *t; | |
1da177e4 LT |
53 | |
54 | tu = file->private_data; | |
3d4e8303 TI |
55 | if (!tu->timeri) |
56 | return -EBADFD; | |
1da177e4 | 57 | t = tu->timeri->timer; |
3d4e8303 TI |
58 | if (!t) |
59 | return -EBADFD; | |
1da177e4 LT |
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 | ||
53d2f744 | 72 | struct snd_timer_status32 { |
1da177e4 LT |
73 | struct compat_timespec tstamp; |
74 | u32 resolution; | |
75 | u32 lost; | |
76 | u32 overrun; | |
77 | u32 queue; | |
78 | unsigned char reserved[64]; | |
79 | }; | |
80 | ||
81 | static int snd_timer_user_status_compat(struct file *file, | |
53d2f744 | 82 | struct snd_timer_status32 __user *_status) |
1da177e4 | 83 | { |
53d2f744 | 84 | struct snd_timer_user *tu; |
3a72494a | 85 | struct snd_timer_status32 status; |
1da177e4 LT |
86 | |
87 | tu = file->private_data; | |
3d4e8303 TI |
88 | if (!tu->timeri) |
89 | return -EBADFD; | |
1da177e4 | 90 | memset(&status, 0, sizeof(status)); |
3a72494a TI |
91 | status.tstamp.tv_sec = tu->tstamp.tv_sec; |
92 | status.tstamp.tv_nsec = tu->tstamp.tv_nsec; | |
1da177e4 LT |
93 | status.resolution = snd_timer_resolution(tu->timeri); |
94 | status.lost = tu->timeri->lost; | |
95 | status.overrun = tu->overrun; | |
96 | spin_lock_irq(&tu->qlock); | |
97 | status.queue = tu->qused; | |
98 | spin_unlock_irq(&tu->qlock); | |
99 | if (copy_to_user(_status, &status, sizeof(status))) | |
100 | return -EFAULT; | |
101 | return 0; | |
102 | } | |
103 | ||
b24e7ad1 TI |
104 | #ifdef CONFIG_X86_X32 |
105 | /* X32 ABI has the same struct as x86-64 */ | |
106 | #define snd_timer_user_status_x32(file, s) \ | |
107 | snd_timer_user_status(file, s) | |
108 | #endif /* CONFIG_X86_X32 */ | |
109 | ||
1da177e4 LT |
110 | /* |
111 | */ | |
112 | ||
113 | enum { | |
91d2178e | 114 | SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32), |
53d2f744 TI |
115 | SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), |
116 | SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), | |
b24e7ad1 TI |
117 | #ifdef CONFIG_X86_X32 |
118 | SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status), | |
119 | #endif /* CONFIG_X86_X32 */ | |
1da177e4 LT |
120 | }; |
121 | ||
79fb0518 TI |
122 | static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, |
123 | unsigned long arg) | |
1da177e4 LT |
124 | { |
125 | void __user *argp = compat_ptr(arg); | |
126 | ||
127 | switch (cmd) { | |
128 | case SNDRV_TIMER_IOCTL_PVERSION: | |
129 | case SNDRV_TIMER_IOCTL_TREAD: | |
130 | case SNDRV_TIMER_IOCTL_GINFO: | |
1da177e4 LT |
131 | case SNDRV_TIMER_IOCTL_GSTATUS: |
132 | case SNDRV_TIMER_IOCTL_SELECT: | |
133 | case SNDRV_TIMER_IOCTL_PARAMS: | |
134 | case SNDRV_TIMER_IOCTL_START: | |
8c50b37c | 135 | case SNDRV_TIMER_IOCTL_START_OLD: |
1da177e4 | 136 | case SNDRV_TIMER_IOCTL_STOP: |
8c50b37c | 137 | case SNDRV_TIMER_IOCTL_STOP_OLD: |
1da177e4 | 138 | case SNDRV_TIMER_IOCTL_CONTINUE: |
8c50b37c | 139 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: |
15790a6b | 140 | case SNDRV_TIMER_IOCTL_PAUSE: |
8c50b37c | 141 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: |
1da177e4 | 142 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: |
79fb0518 | 143 | return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
91d2178e TS |
144 | case SNDRV_TIMER_IOCTL_GPARAMS32: |
145 | return snd_timer_user_gparams_compat(file, argp); | |
1da177e4 LT |
146 | case SNDRV_TIMER_IOCTL_INFO32: |
147 | return snd_timer_user_info_compat(file, argp); | |
148 | case SNDRV_TIMER_IOCTL_STATUS32: | |
149 | return snd_timer_user_status_compat(file, argp); | |
b24e7ad1 TI |
150 | #ifdef CONFIG_X86_X32 |
151 | case SNDRV_TIMER_IOCTL_STATUS_X32: | |
152 | return snd_timer_user_status_x32(file, argp); | |
153 | #endif /* CONFIG_X86_X32 */ | |
1da177e4 LT |
154 | } |
155 | return -ENOIOCTLCMD; | |
156 | } | |
79fb0518 TI |
157 | |
158 | static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, | |
159 | unsigned long arg) | |
160 | { | |
161 | struct snd_timer_user *tu = file->private_data; | |
162 | long ret; | |
163 | ||
164 | mutex_lock(&tu->ioctl_lock); | |
165 | ret = __snd_timer_user_ioctl_compat(file, cmd, arg); | |
166 | mutex_unlock(&tu->ioctl_lock); | |
167 | return ret; | |
168 | } |