.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 32bit -> 64bit ioctl wrapper for PCM API |
---|
3 | 4 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
---|
4 | | - * |
---|
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. |
---|
9 | | - * |
---|
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. |
---|
14 | | - * |
---|
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 |
---|
18 | | - * |
---|
19 | 5 | */ |
---|
20 | 6 | |
---|
21 | 7 | /* This file included from pcm_native.c */ |
---|
.. | .. |
---|
97 | 83 | unsigned char reserved[56]; |
---|
98 | 84 | }; |
---|
99 | 85 | |
---|
100 | | -/* recalcuate the boundary within 32bit */ |
---|
101 | | -static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) |
---|
102 | | -{ |
---|
103 | | - snd_pcm_uframes_t boundary; |
---|
104 | | - |
---|
105 | | - if (! runtime->buffer_size) |
---|
106 | | - return 0; |
---|
107 | | - boundary = runtime->buffer_size; |
---|
108 | | - while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) |
---|
109 | | - boundary *= 2; |
---|
110 | | - return boundary; |
---|
111 | | -} |
---|
112 | | - |
---|
113 | 86 | static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, |
---|
114 | 87 | struct snd_pcm_sw_params32 __user *src) |
---|
115 | 88 | { |
---|
.. | .. |
---|
182 | 155 | snd_pcm_channel_info_user(s, p) |
---|
183 | 156 | #endif /* CONFIG_X86_X32 */ |
---|
184 | 157 | |
---|
185 | | -struct snd_pcm_status32 { |
---|
186 | | - s32 state; |
---|
187 | | - struct compat_timespec trigger_tstamp; |
---|
188 | | - struct compat_timespec tstamp; |
---|
| 158 | +struct compat_snd_pcm_status64 { |
---|
| 159 | + snd_pcm_state_t state; |
---|
| 160 | + u8 rsvd[4]; /* alignment */ |
---|
| 161 | + s64 trigger_tstamp_sec; |
---|
| 162 | + s64 trigger_tstamp_nsec; |
---|
| 163 | + s64 tstamp_sec; |
---|
| 164 | + s64 tstamp_nsec; |
---|
189 | 165 | u32 appl_ptr; |
---|
190 | 166 | u32 hw_ptr; |
---|
191 | 167 | s32 delay; |
---|
192 | 168 | u32 avail; |
---|
193 | 169 | u32 avail_max; |
---|
194 | 170 | u32 overrange; |
---|
195 | | - s32 suspended_state; |
---|
| 171 | + snd_pcm_state_t suspended_state; |
---|
196 | 172 | u32 audio_tstamp_data; |
---|
197 | | - struct compat_timespec audio_tstamp; |
---|
198 | | - struct compat_timespec driver_tstamp; |
---|
| 173 | + s64 audio_tstamp_sec; |
---|
| 174 | + s64 audio_tstamp_nsec; |
---|
| 175 | + s64 driver_tstamp_sec; |
---|
| 176 | + s64 driver_tstamp_nsec; |
---|
199 | 177 | u32 audio_tstamp_accuracy; |
---|
200 | | - unsigned char reserved[52-2*sizeof(struct compat_timespec)]; |
---|
201 | | -} __attribute__((packed)); |
---|
202 | | - |
---|
203 | | - |
---|
204 | | -static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, |
---|
205 | | - struct snd_pcm_status32 __user *src, |
---|
206 | | - bool ext) |
---|
207 | | -{ |
---|
208 | | - struct snd_pcm_status status; |
---|
209 | | - int err; |
---|
210 | | - |
---|
211 | | - memset(&status, 0, sizeof(status)); |
---|
212 | | - /* |
---|
213 | | - * with extension, parameters are read/write, |
---|
214 | | - * get audio_tstamp_data from user, |
---|
215 | | - * ignore rest of status structure |
---|
216 | | - */ |
---|
217 | | - if (ext && get_user(status.audio_tstamp_data, |
---|
218 | | - (u32 __user *)(&src->audio_tstamp_data))) |
---|
219 | | - return -EFAULT; |
---|
220 | | - err = snd_pcm_status(substream, &status); |
---|
221 | | - if (err < 0) |
---|
222 | | - return err; |
---|
223 | | - |
---|
224 | | - if (clear_user(src, sizeof(*src))) |
---|
225 | | - return -EFAULT; |
---|
226 | | - if (put_user(status.state, &src->state) || |
---|
227 | | - compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || |
---|
228 | | - compat_put_timespec(&status.tstamp, &src->tstamp) || |
---|
229 | | - put_user(status.appl_ptr, &src->appl_ptr) || |
---|
230 | | - put_user(status.hw_ptr, &src->hw_ptr) || |
---|
231 | | - put_user(status.delay, &src->delay) || |
---|
232 | | - put_user(status.avail, &src->avail) || |
---|
233 | | - put_user(status.avail_max, &src->avail_max) || |
---|
234 | | - put_user(status.overrange, &src->overrange) || |
---|
235 | | - put_user(status.suspended_state, &src->suspended_state) || |
---|
236 | | - put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || |
---|
237 | | - compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) || |
---|
238 | | - compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) || |
---|
239 | | - put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) |
---|
240 | | - return -EFAULT; |
---|
241 | | - |
---|
242 | | - return err; |
---|
243 | | -} |
---|
244 | | - |
---|
245 | | -#ifdef CONFIG_X86_X32 |
---|
246 | | -/* X32 ABI has 64bit timespec and 64bit alignment */ |
---|
247 | | -struct snd_pcm_status_x32 { |
---|
248 | | - s32 state; |
---|
249 | | - u32 rsvd; /* alignment */ |
---|
250 | | - struct timespec trigger_tstamp; |
---|
251 | | - struct timespec tstamp; |
---|
252 | | - u32 appl_ptr; |
---|
253 | | - u32 hw_ptr; |
---|
254 | | - s32 delay; |
---|
255 | | - u32 avail; |
---|
256 | | - u32 avail_max; |
---|
257 | | - u32 overrange; |
---|
258 | | - s32 suspended_state; |
---|
259 | | - u32 audio_tstamp_data; |
---|
260 | | - struct timespec audio_tstamp; |
---|
261 | | - struct timespec driver_tstamp; |
---|
262 | | - u32 audio_tstamp_accuracy; |
---|
263 | | - unsigned char reserved[52-2*sizeof(struct timespec)]; |
---|
| 178 | + unsigned char reserved[52-4*sizeof(s64)]; |
---|
264 | 179 | } __packed; |
---|
265 | 180 | |
---|
266 | | -#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) |
---|
267 | | - |
---|
268 | | -static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream, |
---|
269 | | - struct snd_pcm_status_x32 __user *src, |
---|
270 | | - bool ext) |
---|
| 181 | +static int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream, |
---|
| 182 | + struct compat_snd_pcm_status64 __user *src, |
---|
| 183 | + bool ext) |
---|
271 | 184 | { |
---|
272 | | - struct snd_pcm_status status; |
---|
| 185 | + struct snd_pcm_status64 status; |
---|
| 186 | + struct compat_snd_pcm_status64 compat_status64; |
---|
273 | 187 | int err; |
---|
274 | 188 | |
---|
275 | 189 | memset(&status, 0, sizeof(status)); |
---|
| 190 | + memset(&compat_status64, 0, sizeof(compat_status64)); |
---|
276 | 191 | /* |
---|
277 | 192 | * with extension, parameters are read/write, |
---|
278 | 193 | * get audio_tstamp_data from user, |
---|
.. | .. |
---|
281 | 196 | if (ext && get_user(status.audio_tstamp_data, |
---|
282 | 197 | (u32 __user *)(&src->audio_tstamp_data))) |
---|
283 | 198 | return -EFAULT; |
---|
284 | | - err = snd_pcm_status(substream, &status); |
---|
| 199 | + err = snd_pcm_status64(substream, &status); |
---|
285 | 200 | if (err < 0) |
---|
286 | 201 | return err; |
---|
287 | 202 | |
---|
288 | 203 | if (clear_user(src, sizeof(*src))) |
---|
289 | 204 | return -EFAULT; |
---|
290 | | - if (put_user(status.state, &src->state) || |
---|
291 | | - put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || |
---|
292 | | - put_timespec(&status.tstamp, &src->tstamp) || |
---|
293 | | - put_user(status.appl_ptr, &src->appl_ptr) || |
---|
294 | | - put_user(status.hw_ptr, &src->hw_ptr) || |
---|
295 | | - put_user(status.delay, &src->delay) || |
---|
296 | | - put_user(status.avail, &src->avail) || |
---|
297 | | - put_user(status.avail_max, &src->avail_max) || |
---|
298 | | - put_user(status.overrange, &src->overrange) || |
---|
299 | | - put_user(status.suspended_state, &src->suspended_state) || |
---|
300 | | - put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || |
---|
301 | | - put_timespec(&status.audio_tstamp, &src->audio_tstamp) || |
---|
302 | | - put_timespec(&status.driver_tstamp, &src->driver_tstamp) || |
---|
303 | | - put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) |
---|
| 205 | + |
---|
| 206 | + compat_status64 = (struct compat_snd_pcm_status64) { |
---|
| 207 | + .state = status.state, |
---|
| 208 | + .trigger_tstamp_sec = status.trigger_tstamp_sec, |
---|
| 209 | + .trigger_tstamp_nsec = status.trigger_tstamp_nsec, |
---|
| 210 | + .tstamp_sec = status.tstamp_sec, |
---|
| 211 | + .tstamp_nsec = status.tstamp_nsec, |
---|
| 212 | + .appl_ptr = status.appl_ptr, |
---|
| 213 | + .hw_ptr = status.hw_ptr, |
---|
| 214 | + .delay = status.delay, |
---|
| 215 | + .avail = status.avail, |
---|
| 216 | + .avail_max = status.avail_max, |
---|
| 217 | + .overrange = status.overrange, |
---|
| 218 | + .suspended_state = status.suspended_state, |
---|
| 219 | + .audio_tstamp_data = status.audio_tstamp_data, |
---|
| 220 | + .audio_tstamp_sec = status.audio_tstamp_sec, |
---|
| 221 | + .audio_tstamp_nsec = status.audio_tstamp_nsec, |
---|
| 222 | + .driver_tstamp_sec = status.audio_tstamp_sec, |
---|
| 223 | + .driver_tstamp_nsec = status.audio_tstamp_nsec, |
---|
| 224 | + .audio_tstamp_accuracy = status.audio_tstamp_accuracy, |
---|
| 225 | + }; |
---|
| 226 | + |
---|
| 227 | + if (copy_to_user(src, &compat_status64, sizeof(compat_status64))) |
---|
304 | 228 | return -EFAULT; |
---|
305 | 229 | |
---|
306 | 230 | return err; |
---|
307 | 231 | } |
---|
308 | | -#endif /* CONFIG_X86_X32 */ |
---|
309 | 232 | |
---|
310 | 233 | /* both for HW_PARAMS and HW_REFINE */ |
---|
311 | 234 | static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, |
---|
.. | .. |
---|
329 | 252 | goto error; |
---|
330 | 253 | } |
---|
331 | 254 | |
---|
332 | | - if (refine) |
---|
| 255 | + if (refine) { |
---|
333 | 256 | err = snd_pcm_hw_refine(substream, data); |
---|
334 | | - else |
---|
| 257 | + if (err < 0) |
---|
| 258 | + goto error; |
---|
| 259 | + err = fixup_unreferenced_params(substream, data); |
---|
| 260 | + } else { |
---|
335 | 261 | err = snd_pcm_hw_params(substream, data); |
---|
| 262 | + } |
---|
336 | 263 | if (err < 0) |
---|
337 | 264 | goto error; |
---|
338 | 265 | if (copy_to_user(data32, data, sizeof(*data32)) || |
---|
.. | .. |
---|
450 | 377 | return err; |
---|
451 | 378 | } |
---|
452 | 379 | |
---|
453 | | - |
---|
454 | | -struct snd_pcm_mmap_status32 { |
---|
455 | | - s32 state; |
---|
456 | | - s32 pad1; |
---|
457 | | - u32 hw_ptr; |
---|
458 | | - struct compat_timespec tstamp; |
---|
459 | | - s32 suspended_state; |
---|
460 | | - struct compat_timespec audio_tstamp; |
---|
461 | | -} __attribute__((packed)); |
---|
462 | | - |
---|
463 | | -struct snd_pcm_mmap_control32 { |
---|
464 | | - u32 appl_ptr; |
---|
465 | | - u32 avail_min; |
---|
466 | | -}; |
---|
467 | | - |
---|
468 | | -struct snd_pcm_sync_ptr32 { |
---|
469 | | - u32 flags; |
---|
470 | | - union { |
---|
471 | | - struct snd_pcm_mmap_status32 status; |
---|
472 | | - unsigned char reserved[64]; |
---|
473 | | - } s; |
---|
474 | | - union { |
---|
475 | | - struct snd_pcm_mmap_control32 control; |
---|
476 | | - unsigned char reserved[64]; |
---|
477 | | - } c; |
---|
478 | | -} __attribute__((packed)); |
---|
479 | | - |
---|
480 | | -static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, |
---|
481 | | - struct snd_pcm_sync_ptr32 __user *src) |
---|
482 | | -{ |
---|
483 | | - struct snd_pcm_runtime *runtime = substream->runtime; |
---|
484 | | - volatile struct snd_pcm_mmap_status *status; |
---|
485 | | - volatile struct snd_pcm_mmap_control *control; |
---|
486 | | - u32 sflags; |
---|
487 | | - struct snd_pcm_mmap_control scontrol; |
---|
488 | | - struct snd_pcm_mmap_status sstatus; |
---|
489 | | - snd_pcm_uframes_t boundary; |
---|
490 | | - int err; |
---|
491 | | - |
---|
492 | | - if (snd_BUG_ON(!runtime)) |
---|
493 | | - return -EINVAL; |
---|
494 | | - |
---|
495 | | - if (get_user(sflags, &src->flags) || |
---|
496 | | - get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || |
---|
497 | | - get_user(scontrol.avail_min, &src->c.control.avail_min)) |
---|
498 | | - return -EFAULT; |
---|
499 | | - if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { |
---|
500 | | - err = snd_pcm_hwsync(substream); |
---|
501 | | - if (err < 0) |
---|
502 | | - return err; |
---|
503 | | - } |
---|
504 | | - status = runtime->status; |
---|
505 | | - control = runtime->control; |
---|
506 | | - boundary = recalculate_boundary(runtime); |
---|
507 | | - if (! boundary) |
---|
508 | | - boundary = 0x7fffffff; |
---|
509 | | - snd_pcm_stream_lock_irq(substream); |
---|
510 | | - /* FIXME: we should consider the boundary for the sync from app */ |
---|
511 | | - if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) |
---|
512 | | - control->appl_ptr = scontrol.appl_ptr; |
---|
513 | | - else |
---|
514 | | - scontrol.appl_ptr = control->appl_ptr % boundary; |
---|
515 | | - if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) |
---|
516 | | - control->avail_min = scontrol.avail_min; |
---|
517 | | - else |
---|
518 | | - scontrol.avail_min = control->avail_min; |
---|
519 | | - sstatus.state = status->state; |
---|
520 | | - sstatus.hw_ptr = status->hw_ptr % boundary; |
---|
521 | | - sstatus.tstamp = status->tstamp; |
---|
522 | | - sstatus.suspended_state = status->suspended_state; |
---|
523 | | - sstatus.audio_tstamp = status->audio_tstamp; |
---|
524 | | - snd_pcm_stream_unlock_irq(substream); |
---|
525 | | - if (put_user(sstatus.state, &src->s.status.state) || |
---|
526 | | - put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || |
---|
527 | | - compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || |
---|
528 | | - put_user(sstatus.suspended_state, &src->s.status.suspended_state) || |
---|
529 | | - compat_put_timespec(&sstatus.audio_tstamp, |
---|
530 | | - &src->s.status.audio_tstamp) || |
---|
531 | | - put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || |
---|
532 | | - put_user(scontrol.avail_min, &src->c.control.avail_min)) |
---|
533 | | - return -EFAULT; |
---|
534 | | - |
---|
535 | | - return 0; |
---|
536 | | -} |
---|
537 | | - |
---|
538 | 380 | #ifdef CONFIG_X86_X32 |
---|
539 | 381 | /* X32 ABI has 64bit timespec and 64bit alignment */ |
---|
540 | 382 | struct snd_pcm_mmap_status_x32 { |
---|
541 | | - s32 state; |
---|
| 383 | + snd_pcm_state_t state; |
---|
542 | 384 | s32 pad1; |
---|
543 | 385 | u32 hw_ptr; |
---|
544 | 386 | u32 pad2; /* alignment */ |
---|
545 | | - struct timespec tstamp; |
---|
546 | | - s32 suspended_state; |
---|
| 387 | + s64 tstamp_sec; |
---|
| 388 | + s64 tstamp_nsec; |
---|
| 389 | + snd_pcm_state_t suspended_state; |
---|
547 | 390 | s32 pad3; |
---|
548 | | - struct timespec audio_tstamp; |
---|
| 391 | + s64 audio_tstamp_sec; |
---|
| 392 | + s64 audio_tstamp_nsec; |
---|
549 | 393 | } __packed; |
---|
550 | 394 | |
---|
551 | 395 | struct snd_pcm_mmap_control_x32 { |
---|
.. | .. |
---|
613 | 457 | snd_pcm_stream_unlock_irq(substream); |
---|
614 | 458 | if (put_user(sstatus.state, &src->s.status.state) || |
---|
615 | 459 | put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || |
---|
616 | | - put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || |
---|
| 460 | + put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) || |
---|
| 461 | + put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) || |
---|
617 | 462 | put_user(sstatus.suspended_state, &src->s.status.suspended_state) || |
---|
618 | | - put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || |
---|
| 463 | + put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) || |
---|
| 464 | + put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) || |
---|
619 | 465 | put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || |
---|
620 | 466 | put_user(scontrol.avail_min, &src->c.control.avail_min)) |
---|
621 | 467 | return -EFAULT; |
---|
.. | .. |
---|
624 | 470 | } |
---|
625 | 471 | #endif /* CONFIG_X86_X32 */ |
---|
626 | 472 | |
---|
| 473 | +#ifdef __BIG_ENDIAN |
---|
| 474 | +typedef char __pad_before_u32[4]; |
---|
| 475 | +typedef char __pad_after_u32[0]; |
---|
| 476 | +#else |
---|
| 477 | +typedef char __pad_before_u32[0]; |
---|
| 478 | +typedef char __pad_after_u32[4]; |
---|
| 479 | +#endif |
---|
| 480 | + |
---|
| 481 | +/* PCM 2.0.15 API definition had a bug in mmap control; it puts the avail_min |
---|
| 482 | + * at the wrong offset due to a typo in padding type. |
---|
| 483 | + * The bug hits only 32bit. |
---|
| 484 | + * A workaround for incorrect read/write is needed only in 32bit compat mode. |
---|
| 485 | + */ |
---|
| 486 | +struct __snd_pcm_mmap_control64_buggy { |
---|
| 487 | + __pad_before_u32 __pad1; |
---|
| 488 | + __u32 appl_ptr; |
---|
| 489 | + __pad_before_u32 __pad2; /* SiC! here is the bug */ |
---|
| 490 | + __pad_before_u32 __pad3; |
---|
| 491 | + __u32 avail_min; |
---|
| 492 | + __pad_after_uframe __pad4; |
---|
| 493 | +}; |
---|
| 494 | + |
---|
| 495 | +static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream, |
---|
| 496 | + struct snd_pcm_sync_ptr __user *_sync_ptr) |
---|
| 497 | +{ |
---|
| 498 | + struct snd_pcm_runtime *runtime = substream->runtime; |
---|
| 499 | + struct snd_pcm_sync_ptr sync_ptr; |
---|
| 500 | + struct __snd_pcm_mmap_control64_buggy *sync_cp; |
---|
| 501 | + volatile struct snd_pcm_mmap_status *status; |
---|
| 502 | + volatile struct snd_pcm_mmap_control *control; |
---|
| 503 | + int err; |
---|
| 504 | + |
---|
| 505 | + memset(&sync_ptr, 0, sizeof(sync_ptr)); |
---|
| 506 | + sync_cp = (struct __snd_pcm_mmap_control64_buggy *)&sync_ptr.c.control; |
---|
| 507 | + if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) |
---|
| 508 | + return -EFAULT; |
---|
| 509 | + if (copy_from_user(sync_cp, &(_sync_ptr->c.control), sizeof(*sync_cp))) |
---|
| 510 | + return -EFAULT; |
---|
| 511 | + status = runtime->status; |
---|
| 512 | + control = runtime->control; |
---|
| 513 | + if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { |
---|
| 514 | + err = snd_pcm_hwsync(substream); |
---|
| 515 | + if (err < 0) |
---|
| 516 | + return err; |
---|
| 517 | + } |
---|
| 518 | + snd_pcm_stream_lock_irq(substream); |
---|
| 519 | + if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { |
---|
| 520 | + err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr); |
---|
| 521 | + if (err < 0) { |
---|
| 522 | + snd_pcm_stream_unlock_irq(substream); |
---|
| 523 | + return err; |
---|
| 524 | + } |
---|
| 525 | + } else { |
---|
| 526 | + sync_cp->appl_ptr = control->appl_ptr; |
---|
| 527 | + } |
---|
| 528 | + if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) |
---|
| 529 | + control->avail_min = sync_cp->avail_min; |
---|
| 530 | + else |
---|
| 531 | + sync_cp->avail_min = control->avail_min; |
---|
| 532 | + sync_ptr.s.status.state = status->state; |
---|
| 533 | + sync_ptr.s.status.hw_ptr = status->hw_ptr; |
---|
| 534 | + sync_ptr.s.status.tstamp = status->tstamp; |
---|
| 535 | + sync_ptr.s.status.suspended_state = status->suspended_state; |
---|
| 536 | + sync_ptr.s.status.audio_tstamp = status->audio_tstamp; |
---|
| 537 | + snd_pcm_stream_unlock_irq(substream); |
---|
| 538 | + if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) |
---|
| 539 | + return -EFAULT; |
---|
| 540 | + return 0; |
---|
| 541 | +} |
---|
| 542 | + |
---|
627 | 543 | /* |
---|
628 | 544 | */ |
---|
629 | 545 | enum { |
---|
630 | 546 | SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32), |
---|
631 | 547 | SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), |
---|
632 | 548 | SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), |
---|
633 | | - SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32), |
---|
634 | | - SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32), |
---|
| 549 | + SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32), |
---|
| 550 | + SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32), |
---|
635 | 551 | SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), |
---|
636 | 552 | SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), |
---|
637 | 553 | SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), |
---|
.. | .. |
---|
640 | 556 | SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32), |
---|
641 | 557 | SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), |
---|
642 | 558 | SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), |
---|
643 | | - SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), |
---|
| 559 | + SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64), |
---|
| 560 | + SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64), |
---|
644 | 561 | #ifdef CONFIG_X86_X32 |
---|
645 | 562 | SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info), |
---|
646 | | - SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32), |
---|
647 | | - SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32), |
---|
648 | 563 | SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32), |
---|
649 | 564 | #endif /* CONFIG_X86_X32 */ |
---|
650 | 565 | }; |
---|
.. | .. |
---|
664 | 579 | |
---|
665 | 580 | /* |
---|
666 | 581 | * When PCM is used on 32bit mode, we need to disable |
---|
667 | | - * mmap of PCM status/control records because of the size |
---|
668 | | - * incompatibility. |
---|
| 582 | + * mmap of the old PCM status/control records because |
---|
| 583 | + * of the size incompatibility. |
---|
669 | 584 | */ |
---|
670 | 585 | pcm_file->no_compat_mmap = 1; |
---|
671 | 586 | |
---|
.. | .. |
---|
687 | 602 | case SNDRV_PCM_IOCTL_XRUN: |
---|
688 | 603 | case SNDRV_PCM_IOCTL_LINK: |
---|
689 | 604 | case SNDRV_PCM_IOCTL_UNLINK: |
---|
| 605 | + case __SNDRV_PCM_IOCTL_SYNC_PTR32: |
---|
690 | 606 | return snd_pcm_common_ioctl(file, substream, cmd, argp); |
---|
| 607 | + case __SNDRV_PCM_IOCTL_SYNC_PTR64: |
---|
| 608 | +#ifdef CONFIG_X86_X32 |
---|
| 609 | + if (in_x32_syscall()) |
---|
| 610 | + return snd_pcm_ioctl_sync_ptr_x32(substream, argp); |
---|
| 611 | +#endif /* CONFIG_X86_X32 */ |
---|
| 612 | + return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); |
---|
691 | 613 | case SNDRV_PCM_IOCTL_HW_REFINE32: |
---|
692 | 614 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); |
---|
693 | 615 | case SNDRV_PCM_IOCTL_HW_PARAMS32: |
---|
694 | 616 | return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); |
---|
695 | 617 | case SNDRV_PCM_IOCTL_SW_PARAMS32: |
---|
696 | 618 | return snd_pcm_ioctl_sw_params_compat(substream, argp); |
---|
697 | | - case SNDRV_PCM_IOCTL_STATUS32: |
---|
698 | | - return snd_pcm_status_user_compat(substream, argp, false); |
---|
699 | | - case SNDRV_PCM_IOCTL_STATUS_EXT32: |
---|
700 | | - return snd_pcm_status_user_compat(substream, argp, true); |
---|
701 | | - case SNDRV_PCM_IOCTL_SYNC_PTR32: |
---|
702 | | - return snd_pcm_ioctl_sync_ptr_compat(substream, argp); |
---|
| 619 | + case SNDRV_PCM_IOCTL_STATUS_COMPAT32: |
---|
| 620 | + return snd_pcm_status_user32(substream, argp, false); |
---|
| 621 | + case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32: |
---|
| 622 | + return snd_pcm_status_user32(substream, argp, true); |
---|
703 | 623 | case SNDRV_PCM_IOCTL_CHANNEL_INFO32: |
---|
704 | 624 | return snd_pcm_ioctl_channel_info_compat(substream, argp); |
---|
705 | 625 | case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: |
---|
.. | .. |
---|
716 | 636 | return snd_pcm_ioctl_rewind_compat(substream, argp); |
---|
717 | 637 | case SNDRV_PCM_IOCTL_FORWARD32: |
---|
718 | 638 | return snd_pcm_ioctl_forward_compat(substream, argp); |
---|
| 639 | + case SNDRV_PCM_IOCTL_STATUS_COMPAT64: |
---|
| 640 | + return snd_pcm_status_user_compat64(substream, argp, false); |
---|
| 641 | + case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: |
---|
| 642 | + return snd_pcm_status_user_compat64(substream, argp, true); |
---|
719 | 643 | #ifdef CONFIG_X86_X32 |
---|
720 | | - case SNDRV_PCM_IOCTL_STATUS_X32: |
---|
721 | | - return snd_pcm_status_user_x32(substream, argp, false); |
---|
722 | | - case SNDRV_PCM_IOCTL_STATUS_EXT_X32: |
---|
723 | | - return snd_pcm_status_user_x32(substream, argp, true); |
---|
724 | | - case SNDRV_PCM_IOCTL_SYNC_PTR_X32: |
---|
725 | | - return snd_pcm_ioctl_sync_ptr_x32(substream, argp); |
---|
726 | 644 | case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: |
---|
727 | 645 | return snd_pcm_ioctl_channel_info_x32(substream, argp); |
---|
728 | 646 | #endif /* CONFIG_X86_X32 */ |
---|