2 * 32bit -> 64bit ioctl wrapper for timer API
3 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* This file included from timer.c */
23 #include <linux/compat.h>
26 * ILP32/LP64 has different size for 'long' type. Additionally, the size
27 * of storage alignment differs depending on architectures. Here, '__packed'
28 * qualifier is used so that the size of this structure is multiple of 4 and
29 * it fits to any architectures with 32 bit storage alignment.
31 struct snd_timer_gparams32
{
32 struct snd_timer_id tid
;
35 unsigned char reserved
[32];
38 struct snd_timer_info32
{
42 unsigned char name
[80];
45 unsigned char reserved
[64];
48 static int snd_timer_user_gparams_compat(struct file
*file
,
49 struct snd_timer_gparams32 __user
*user
)
51 struct snd_timer_gparams gparams
;
53 if (copy_from_user(&gparams
.tid
, &user
->tid
, sizeof(gparams
.tid
)) ||
54 get_user(gparams
.period_num
, &user
->period_num
) ||
55 get_user(gparams
.period_den
, &user
->period_den
))
58 return timer_set_gparams(&gparams
);
61 static int snd_timer_user_info_compat(struct file
*file
,
62 struct snd_timer_info32 __user
*_info
)
64 struct snd_timer_user
*tu
;
65 struct snd_timer_info32 info
;
68 tu
= file
->private_data
;
71 t
= tu
->timeri
->timer
;
74 memset(&info
, 0, sizeof(info
));
75 info
.card
= t
->card
? t
->card
->number
: -1;
76 if (t
->hw
.flags
& SNDRV_TIMER_HW_SLAVE
)
77 info
.flags
|= SNDRV_TIMER_FLG_SLAVE
;
78 strlcpy(info
.id
, t
->id
, sizeof(info
.id
));
79 strlcpy(info
.name
, t
->name
, sizeof(info
.name
));
80 info
.resolution
= t
->hw
.resolution
;
81 if (copy_to_user(_info
, &info
, sizeof(*_info
)))
86 struct snd_timer_status32
{
87 struct compat_timespec tstamp
;
92 unsigned char reserved
[64];
95 static int snd_timer_user_status_compat(struct file
*file
,
96 struct snd_timer_status32 __user
*_status
)
98 struct snd_timer_user
*tu
;
99 struct snd_timer_status32 status
;
101 tu
= file
->private_data
;
104 memset(&status
, 0, sizeof(status
));
105 status
.tstamp
.tv_sec
= tu
->tstamp
.tv_sec
;
106 status
.tstamp
.tv_nsec
= tu
->tstamp
.tv_nsec
;
107 status
.resolution
= snd_timer_resolution(tu
->timeri
);
108 status
.lost
= tu
->timeri
->lost
;
109 status
.overrun
= tu
->overrun
;
110 spin_lock_irq(&tu
->qlock
);
111 status
.queue
= tu
->qused
;
112 spin_unlock_irq(&tu
->qlock
);
113 if (copy_to_user(_status
, &status
, sizeof(status
)))
118 #ifdef CONFIG_X86_X32
119 /* X32 ABI has the same struct as x86-64 */
120 #define snd_timer_user_status_x32(file, s) \
121 snd_timer_user_status(file, s)
122 #endif /* CONFIG_X86_X32 */
128 SNDRV_TIMER_IOCTL_GPARAMS32
= _IOW('T', 0x04, struct snd_timer_gparams32
),
129 SNDRV_TIMER_IOCTL_INFO32
= _IOR('T', 0x11, struct snd_timer_info32
),
130 SNDRV_TIMER_IOCTL_STATUS32
= _IOW('T', 0x14, struct snd_timer_status32
),
131 #ifdef CONFIG_X86_X32
132 SNDRV_TIMER_IOCTL_STATUS_X32
= _IOW('T', 0x14, struct snd_timer_status
),
133 #endif /* CONFIG_X86_X32 */
136 static long __snd_timer_user_ioctl_compat(struct file
*file
, unsigned int cmd
,
139 void __user
*argp
= compat_ptr(arg
);
142 case SNDRV_TIMER_IOCTL_PVERSION
:
143 case SNDRV_TIMER_IOCTL_TREAD
:
144 case SNDRV_TIMER_IOCTL_GINFO
:
145 case SNDRV_TIMER_IOCTL_GSTATUS
:
146 case SNDRV_TIMER_IOCTL_SELECT
:
147 case SNDRV_TIMER_IOCTL_PARAMS
:
148 case SNDRV_TIMER_IOCTL_START
:
149 case SNDRV_TIMER_IOCTL_START_OLD
:
150 case SNDRV_TIMER_IOCTL_STOP
:
151 case SNDRV_TIMER_IOCTL_STOP_OLD
:
152 case SNDRV_TIMER_IOCTL_CONTINUE
:
153 case SNDRV_TIMER_IOCTL_CONTINUE_OLD
:
154 case SNDRV_TIMER_IOCTL_PAUSE
:
155 case SNDRV_TIMER_IOCTL_PAUSE_OLD
:
156 case SNDRV_TIMER_IOCTL_NEXT_DEVICE
:
157 return __snd_timer_user_ioctl(file
, cmd
, (unsigned long)argp
);
158 case SNDRV_TIMER_IOCTL_GPARAMS32
:
159 return snd_timer_user_gparams_compat(file
, argp
);
160 case SNDRV_TIMER_IOCTL_INFO32
:
161 return snd_timer_user_info_compat(file
, argp
);
162 case SNDRV_TIMER_IOCTL_STATUS32
:
163 return snd_timer_user_status_compat(file
, argp
);
164 #ifdef CONFIG_X86_X32
165 case SNDRV_TIMER_IOCTL_STATUS_X32
:
166 return snd_timer_user_status_x32(file
, argp
);
167 #endif /* CONFIG_X86_X32 */
172 static long snd_timer_user_ioctl_compat(struct file
*file
, unsigned int cmd
,
175 struct snd_timer_user
*tu
= file
->private_data
;
178 mutex_lock(&tu
->ioctl_lock
);
179 ret
= __snd_timer_user_ioctl_compat(file
, cmd
, arg
);
180 mutex_unlock(&tu
->ioctl_lock
);