staticint snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, int dir, struct snd_xferi32 __user *data32)
{
compat_caddr_t buf;
u32 frames; int err;
if (! substream->runtime) return -ENOTTY; if (substream->stream != dir) return -EINVAL; if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD;
if (get_user(buf, &data32->buf) ||
get_user(frames, &data32->frames)) return -EFAULT;
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_lib_write(substream, compat_ptr(buf), frames); else
err = snd_pcm_lib_read(substream, compat_ptr(buf), frames); if (err < 0) return err; /* copy the result */ if (put_user(err, &data32->result)) return -EFAULT; return 0;
}
/* snd_xfern needs remapping of bufs */ struct snd_xfern32 {
s32 result;
u32 bufs; /* this is void **; */
u32 frames;
};
/* * xfern ioctl nees to copy (up to) 128 pointers on stack. * although we may pass the copied pointers through f_op->ioctl, but the ioctl * handler there expands again the same 128 pointers on stack, so it is better * to handle the function (calling pcm_readv/writev) directly in this handler.
*/ staticint snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, int dir, struct snd_xfern32 __user *data32)
{
compat_caddr_t buf;
compat_caddr_t __user *bufptr;
u32 frames; void __user **bufs __free(kfree) = NULL; int err, ch, i;
if (! substream->runtime) return -ENOTTY; if (substream->stream != dir) return -EINVAL; if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD;
ch = substream->runtime->channels; if (ch > 128) return -EINVAL; if (get_user(buf, &data32->bufs) ||
get_user(frames, &data32->frames)) return -EFAULT;
bufptr = compat_ptr(buf);
bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL); if (bufs == NULL) return -ENOMEM; for (i = 0; i < ch; i++) {
u32 ptr; if (get_user(ptr, bufptr)) return -EFAULT;
bufs[i] = compat_ptr(ptr);
bufptr++;
} if (dir == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_lib_writev(substream, bufs, frames); else
err = snd_pcm_lib_readv(substream, bufs, frames); if (err >= 0) { if (put_user(err, &data32->result)) return -EFAULT;
} return err;
}
/* PCM 2.0.15 API definition had a bug in mmap control; it puts the avail_min * at the wrong offset due to a typo in padding type. * The bug hits only 32bit. * A workaround for incorrect read/write is needed only in 32bit compat mode.
*/ struct __snd_pcm_mmap_control64_buggy {
__pad_before_u32 __pad1;
__u32 appl_ptr;
__pad_before_u32 __pad2; /* SiC! here is the bug */
__pad_before_u32 __pad3;
__u32 avail_min;
__pad_after_uframe __pad4;
};
pcm_file = file->private_data; if (! pcm_file) return -ENOTTY;
substream = pcm_file->substream; if (! substream) return -ENOTTY;
/* * When PCM is used on 32bit mode, we need to disable * mmap of the old PCM status/control records because * of the size incompatibility.
*/
pcm_file->no_compat_mmap = 1;
switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: case SNDRV_PCM_IOCTL_INFO: case SNDRV_PCM_IOCTL_TSTAMP: case SNDRV_PCM_IOCTL_TTSTAMP: case SNDRV_PCM_IOCTL_USER_PVERSION: case SNDRV_PCM_IOCTL_HWSYNC: case SNDRV_PCM_IOCTL_PREPARE: case SNDRV_PCM_IOCTL_RESET: case SNDRV_PCM_IOCTL_START: case SNDRV_PCM_IOCTL_DROP: case SNDRV_PCM_IOCTL_DRAIN: case SNDRV_PCM_IOCTL_PAUSE: case SNDRV_PCM_IOCTL_HW_FREE: case SNDRV_PCM_IOCTL_RESUME: case SNDRV_PCM_IOCTL_XRUN: case SNDRV_PCM_IOCTL_LINK: case SNDRV_PCM_IOCTL_UNLINK: case __SNDRV_PCM_IOCTL_SYNC_PTR32: return snd_pcm_common_ioctl(file, substream, cmd, argp); case __SNDRV_PCM_IOCTL_SYNC_PTR64: #ifdef CONFIG_X86_X32_ABI if (in_x32_syscall()) return snd_pcm_ioctl_sync_ptr_x32(substream, argp); #endif/* CONFIG_X86_X32_ABI */ return snd_pcm_ioctl_sync_ptr_buggy(substream, argp); case SNDRV_PCM_IOCTL_HW_REFINE32: return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); case SNDRV_PCM_IOCTL_HW_PARAMS32: return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); case SNDRV_PCM_IOCTL_SW_PARAMS32: return snd_pcm_ioctl_sw_params_compat(substream, argp); case SNDRV_PCM_IOCTL_STATUS_COMPAT32: return snd_pcm_status_user32(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32: return snd_pcm_status_user32(substream, argp, true); case SNDRV_PCM_IOCTL_CHANNEL_INFO32: return snd_pcm_ioctl_channel_info_compat(substream, argp); case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); case SNDRV_PCM_IOCTL_READI_FRAMES32: return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); case SNDRV_PCM_IOCTL_WRITEN_FRAMES32: return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); case SNDRV_PCM_IOCTL_READN_FRAMES32: return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); case SNDRV_PCM_IOCTL_DELAY32: return snd_pcm_ioctl_delay_compat(substream, argp); case SNDRV_PCM_IOCTL_REWIND32: return snd_pcm_ioctl_rewind_compat(substream, argp); case SNDRV_PCM_IOCTL_FORWARD32: return snd_pcm_ioctl_forward_compat(substream, argp); case SNDRV_PCM_IOCTL_STATUS_COMPAT64: return snd_pcm_status_user_compat64(substream, argp, false); case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64: return snd_pcm_status_user_compat64(substream, argp, true); #ifdef CONFIG_X86_X32_ABI case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32: return snd_pcm_ioctl_channel_info_x32(substream, argp); #endif/* CONFIG_X86_X32_ABI */
}
return -ENOIOCTLCMD;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.