📄 compat_ioctl32.c
字号:
/* * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de> * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. */#include "compat.h"#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)#include <linux/config.h>#include <linux/compat.h>#include <linux/videodev.h>#include <linux/videodev2.h>#include <linux/module.h>#include <linux/smp_lock.h>#include <media/v4l2-common.h>#ifdef CONFIG_COMPATstruct video_tuner32 { compat_int_t tuner; char name[32]; compat_ulong_t rangelow, rangehigh; u32 flags; /* It is really u32 in videodev.h */ u16 mode, signal;};static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up){ if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || get_user(kp->tuner, &up->tuner) || copy_from_user(kp->name, up->name, 32) || get_user(kp->rangelow, &up->rangelow) || get_user(kp->rangehigh, &up->rangehigh) || get_user(kp->flags, &up->flags) || get_user(kp->mode, &up->mode) || get_user(kp->signal, &up->signal)) return -EFAULT; return 0;}static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up){ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || put_user(kp->tuner, &up->tuner) || copy_to_user(up->name, kp->name, 32) || put_user(kp->rangelow, &up->rangelow) || put_user(kp->rangehigh, &up->rangehigh) || put_user(kp->flags, &up->flags) || put_user(kp->mode, &up->mode) || put_user(kp->signal, &up->signal)) return -EFAULT; return 0;}struct video_buffer32 { compat_caddr_t base; compat_int_t height, width, depth, bytesperline;};static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up){ u32 tmp; if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || get_user(tmp, &up->base) || get_user(kp->height, &up->height) || get_user(kp->width, &up->width) || get_user(kp->depth, &up->depth) || get_user(kp->bytesperline, &up->bytesperline)) return -EFAULT; /* This is actually a physical address stored * as a void pointer. */ kp->base = (void *)(unsigned long) tmp; return 0;}static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up){ u32 tmp = (u32)((unsigned long)kp->base); if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || put_user(tmp, &up->base) || put_user(kp->height, &up->height) || put_user(kp->width, &up->width) || put_user(kp->depth, &up->depth) || put_user(kp->bytesperline, &up->bytesperline)) return -EFAULT; return 0;}struct video_clip32 { s32 x, y, width, height; /* Its really s32 in videodev.h */ compat_caddr_t next;};struct video_window32 { u32 x, y, width, height, chromakey, flags; compat_caddr_t clips; compat_int_t clipcount;};static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ int ret = -ENOIOCTLCMD; if (file->f_op->unlocked_ioctl) ret = file->f_op->unlocked_ioctl(file, cmd, arg); else if (file->f_op->ioctl) { lock_kernel(); ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); unlock_kernel(); } return ret;}/* You get back everything except the clips... */static int put_video_window32(struct video_window *kp, struct video_window32 __user *up){ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || put_user(kp->x, &up->x) || put_user(kp->y, &up->y) || put_user(kp->width, &up->width) || put_user(kp->height, &up->height) || put_user(kp->chromakey, &up->chromakey) || put_user(kp->flags, &up->flags) || put_user(kp->clipcount, &up->clipcount)) return -EFAULT; return 0;}struct v4l2_clip32{ struct v4l2_rect c; compat_caddr_t next;};struct v4l2_window32{ struct v4l2_rect w; enum v4l2_field field; __u32 chromakey; compat_caddr_t clips; /* actually struct v4l2_clip32 * */ __u32 clipcount; compat_caddr_t bitmap;};static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up){ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || get_user(kp->chromakey, &up->chromakey) || get_user(kp->clipcount, &up->clipcount)) return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; if (kp->clipcount) { struct v4l2_clip32 __user *uclips; struct v4l2_clip __user *kclips; int n = kp->clipcount; compat_caddr_t p; if (get_user(p, &up->clips)) return -EFAULT; uclips = compat_ptr(p); kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); kp->clips = kclips; while (--n >= 0) { if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) return -EFAULT; if (put_user(n ? kclips + 1 : NULL, &kclips->next)) return -EFAULT; uclips += 1; kclips += 1; } } else kp->clips = NULL; return 0;}static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up){ if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || put_user(kp->clipcount, &up->clipcount)) return -EFAULT; return 0;}static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up){ if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) return -EFAULT; return 0;}static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up){ if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) return -EFAULT; return 0;}static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up){ if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) return -EFAULT; return 0;}static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up){ if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) return -EFAULT; return 0;}struct v4l2_format32{ enum v4l2_buf_type type; union { struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE __u8 raw_data[200]; // user-defined } fmt;};static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up){ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || get_user(kp->type, &up->type)) return -EFAULT; switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); case V4L2_BUF_TYPE_VIDEO_OVERLAY: return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); default: printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n", kp->type); return -ENXIO; }}static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up){ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || put_user(kp->type, &up->type)) return -EFAULT; switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); case V4L2_BUF_TYPE_VIDEO_OVERLAY: return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); default: return -ENXIO; }}static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up){ if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) return -EFAULT; return 0;}static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up){ if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) return -EFAULT; return 0;}struct v4l2_standard32{ __u32 index; __u32 id[2]; /* __u64 would get the alignment wrong */ __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ __u32 framelines; __u32 reserved[4];};static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up){ /* other fields are not set by the user, nor used by the driver */ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || get_user(kp->index, &up->index)) return -EFAULT; return 0;}static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up){ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || put_user(kp->index, &up->index) || copy_to_user(up->id, &kp->id, sizeof(__u64)) || copy_to_user(up->name, kp->name, 24) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) return -EFAULT; return 0;}static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up){ if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) return -EFAULT; return 0;}static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up){ if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) return -EFAULT; return 0;}struct v4l2_buffer32{ __u32 index; enum v4l2_buf_type type; __u32 bytesused; __u32 flags; enum v4l2_field field; struct compat_timeval timestamp; struct v4l2_timecode timecode; __u32 sequence; /* memory location */ enum v4l2_memory memory; union { __u32 offset; compat_long_t userptr; } m; __u32 length; __u32 input; __u32 reserved;};static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up){ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || get_user(kp->memory, &up->memory) || get_user(kp->input, &up->input)) return -EFAULT; switch(kp->memory) { case V4L2_MEMORY_MMAP: break; case V4L2_MEMORY_USERPTR: { compat_long_t tmp; if (get_user(kp->length, &up->length) || get_user(tmp, &up->m.userptr)) return -EFAULT; kp->m.userptr = (unsigned long)compat_ptr(tmp); } break; case V4L2_MEMORY_OVERLAY: if(get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; } return 0;}static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up){ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || put_user(kp->index, &up->index) || put_user(kp->type, &up->type) || put_user(kp->flags, &up->flags) || put_user(kp->memory, &up->memory) || put_user(kp->input, &up->input)) return -EFAULT; switch(kp->memory) { case V4L2_MEMORY_MMAP: if (put_user(kp->length, &up->length) || put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: if (put_user(kp->length, &up->length) || put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; } if (put_user(kp->bytesused, &up->bytesused) || put_user(kp->field, &up->field) || put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved, &up->reserved)) return -EFAULT; return 0;}struct v4l2_framebuffer32{ __u32 capability; __u32 flags; compat_caddr_t base; struct v4l2_pix_format fmt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -