1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * 32bit -> 64bit ioctl wrapper for timer API
4 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
7 /* This file included from timer.c */
9 #include <linux/compat.h>
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.
17 struct snd_timer_gparams32
{
18 struct snd_timer_id tid
;
21 unsigned char reserved
[32];
24 struct snd_timer_info32
{
28 unsigned char name
[80];
31 unsigned char reserved
[64];
34 static int snd_timer_user_gparams_compat(struct file
*file
,
35 struct snd_timer_gparams32 __user
*user
)
37 struct snd_timer_gparams gparams
;
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
))
44 return timer_set_gparams(&gparams
);
47 static int snd_timer_user_info_compat(struct file
*file
,
48 struct snd_timer_info32 __user
*_info
)
50 struct snd_timer_user
*tu
;
51 struct snd_timer_info32 info
;
54 tu
= file
->private_data
;
57 t
= tu
->timeri
->timer
;
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
)))
72 struct snd_timer_status32
{
73 struct compat_timespec tstamp
;
78 unsigned char reserved
[64];
81 static int snd_timer_user_status_compat(struct file
*file
,
82 struct snd_timer_status32 __user
*_status
)
84 struct snd_timer_user
*tu
;
85 struct snd_timer_status32 status
;
87 tu
= file
->private_data
;
90 memset(&status
, 0, sizeof(status
));
91 status
.tstamp
.tv_sec
= tu
->tstamp
.tv_sec
;
92 status
.tstamp
.tv_nsec
= tu
->tstamp
.tv_nsec
;
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
)))
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 */
114 SNDRV_TIMER_IOCTL_GPARAMS32
= _IOW('T', 0x04, struct snd_timer_gparams32
),
115 SNDRV_TIMER_IOCTL_INFO32
= _IOR('T', 0x11, struct snd_timer_info32
),
116 SNDRV_TIMER_IOCTL_STATUS32
= _IOW('T', 0x14, struct snd_timer_status32
),
117 #ifdef CONFIG_X86_X32
118 SNDRV_TIMER_IOCTL_STATUS_X32
= _IOW('T', 0x14, struct snd_timer_status
),
119 #endif /* CONFIG_X86_X32 */
122 static long __snd_timer_user_ioctl_compat(struct file
*file
, unsigned int cmd
,
125 void __user
*argp
= compat_ptr(arg
);
128 case SNDRV_TIMER_IOCTL_PVERSION
:
129 case SNDRV_TIMER_IOCTL_TREAD
:
130 case SNDRV_TIMER_IOCTL_GINFO
:
131 case SNDRV_TIMER_IOCTL_GSTATUS
:
132 case SNDRV_TIMER_IOCTL_SELECT
:
133 case SNDRV_TIMER_IOCTL_PARAMS
:
134 case SNDRV_TIMER_IOCTL_START
:
135 case SNDRV_TIMER_IOCTL_START_OLD
:
136 case SNDRV_TIMER_IOCTL_STOP
:
137 case SNDRV_TIMER_IOCTL_STOP_OLD
:
138 case SNDRV_TIMER_IOCTL_CONTINUE
:
139 case SNDRV_TIMER_IOCTL_CONTINUE_OLD
:
140 case SNDRV_TIMER_IOCTL_PAUSE
:
141 case SNDRV_TIMER_IOCTL_PAUSE_OLD
:
142 case SNDRV_TIMER_IOCTL_NEXT_DEVICE
:
143 return __snd_timer_user_ioctl(file
, cmd
, (unsigned long)argp
);
144 case SNDRV_TIMER_IOCTL_GPARAMS32
:
145 return snd_timer_user_gparams_compat(file
, argp
);
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
);
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 */
158 static long snd_timer_user_ioctl_compat(struct file
*file
, unsigned int cmd
,
161 struct snd_timer_user
*tu
= file
->private_data
;
164 mutex_lock(&tu
->ioctl_lock
);
165 ret
= __snd_timer_user_ioctl_compat(file
, cmd
, arg
);
166 mutex_unlock(&tu
->ioctl_lock
);