#endif
-static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- int ret = -ENOIOCTLCMD;
+ long ret = -ENOIOCTLCMD;
if (file->f_op->unlocked_ioctl)
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
};
+struct v4l2_ext_control32 {
+ __u32 id;
+ __u32 size;
+ __u32 reserved2[1];
+ union {
+ __s32 value;
+ __s64 value64;
+ compat_caddr_t string; /* actually char * */
+ };
+} __attribute__ ((packed));
+
+/* The following function really belong in v4l2-common, but that causes
+ a circular dependency between modules. We need to think about this, but
+ for now this will do. */
+
+/* Return non-zero if this control is a pointer type. Currently only
+ type STRING is a pointer type. */
+static inline int ctrl_is_pointer(u32 id)
+{
+ switch (id) {
+ case V4L2_CID_RDS_TX_PS_NAME:
+ case V4L2_CID_RDS_TX_RADIO_TEXT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
{
- struct v4l2_ext_control __user *ucontrols;
+ struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols;
int n;
compat_caddr_t p;
kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
kp->controls = kcontrols;
while (--n >= 0) {
- if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
- return -EFAULT;
- if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
- return -EFAULT;
- /* Note: if the void * part of the union ever becomes relevant
- then we need to know the type of the control in order to do
- the right thing here. Luckily, that is not yet an issue. */
- if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
+ if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
return -EFAULT;
+ if (ctrl_is_pointer(kcontrols->id)) {
+ void __user *s;
+
+ if (get_user(p, &ucontrols->string))
+ return -EFAULT;
+ s = compat_ptr(p);
+ if (put_user(s, &kcontrols->string))
+ return -EFAULT;
+ }
ucontrols++;
kcontrols++;
}
static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
{
- struct v4l2_ext_control __user *ucontrols;
+ struct v4l2_ext_control32 __user *ucontrols;
struct v4l2_ext_control __user *kcontrols = kp->controls;
int n = kp->count;
compat_caddr_t p;
return -EFAULT;
while (--n >= 0) {
- if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
- return -EFAULT;
- if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
- sizeof(ucontrols->reserved2)))
- return -EFAULT;
- /* Note: if the void * part of the union ever becomes relevant
- then we need to know the type of the control in order to do
- the right thing here. Luckily, that is not yet an issue. */
- if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
+ unsigned size = sizeof(*ucontrols);
+
+ /* Do not modify the pointer when copying a pointer control.
+ The contents of the pointer was changed, not the pointer
+ itself. */
+ if (ctrl_is_pointer(kcontrols->id))
+ size -= sizeof(ucontrols->value64);
+ if (copy_in_user(ucontrols, kcontrols, size))
return -EFAULT;
ucontrols++;
kcontrols++;
#define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
#define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
+#ifdef __OLD_VIDIOC_
#define VIDIOC_OVERLAY32_OLD _IOWR('V', 14, s32)
+#endif
#define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
#define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
#define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
-static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
union {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
} karg;
void __user *up = compat_ptr(arg);
int compatible_arg = 1;
- int err = 0;
+ long err = 0;
/* First, convert the command. */
switch (cmd) {
case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
+#ifdef __OLD_VIDIOC_
case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
+#endif
case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
return err;
}
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
{
- int ret = -ENOIOCTLCMD;
+ long ret = -ENOIOCTLCMD;
if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
return ret;
case VIDIOC_TRY_ENCODER_CMD:
case VIDIOC_DBG_S_REGISTER:
case VIDIOC_DBG_G_REGISTER:
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
case VIDIOC_S_HW_FREQ_SEEK:
ret = do_video_ioctl(file, cmd, arg);
break;
break;
#endif
default:
- v4l_print_ioctl("compat_ioctl32", cmd);
- printk(KERN_CONT "\n");
+ printk(KERN_WARNING "compat_ioctl32: "
+ "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
break;
}
return ret;
}
-#else
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
+EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
#endif
-EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
MODULE_LICENSE("GPL");