0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/compat.h>
0018 #include <linux/module.h>
0019 #include <linux/videodev2.h>
0020 #include <linux/v4l2-subdev.h>
0021 #include <media/v4l2-dev.h>
0022 #include <media/v4l2-fh.h>
0023 #include <media/v4l2-ctrls.h>
0024 #include <media/v4l2-ioctl.h>
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 struct v4l2_clip32 {
0042 struct v4l2_rect c;
0043 compat_caddr_t next;
0044 };
0045
0046 struct v4l2_window32 {
0047 struct v4l2_rect w;
0048 __u32 field;
0049 __u32 chromakey;
0050 compat_caddr_t clips;
0051 __u32 clipcount;
0052 compat_caddr_t bitmap;
0053 __u8 global_alpha;
0054 };
0055
0056 static int get_v4l2_window32(struct v4l2_window *p64,
0057 struct v4l2_window32 __user *p32)
0058 {
0059 struct v4l2_window32 w32;
0060
0061 if (copy_from_user(&w32, p32, sizeof(w32)))
0062 return -EFAULT;
0063
0064 *p64 = (struct v4l2_window) {
0065 .w = w32.w,
0066 .field = w32.field,
0067 .chromakey = w32.chromakey,
0068 .clips = (void __force *)compat_ptr(w32.clips),
0069 .clipcount = w32.clipcount,
0070 .bitmap = compat_ptr(w32.bitmap),
0071 .global_alpha = w32.global_alpha,
0072 };
0073
0074 if (p64->clipcount > 2048)
0075 return -EINVAL;
0076 if (!p64->clipcount)
0077 p64->clips = NULL;
0078
0079 return 0;
0080 }
0081
0082 static int put_v4l2_window32(struct v4l2_window *p64,
0083 struct v4l2_window32 __user *p32)
0084 {
0085 struct v4l2_window32 w32;
0086
0087 memset(&w32, 0, sizeof(w32));
0088 w32 = (struct v4l2_window32) {
0089 .w = p64->w,
0090 .field = p64->field,
0091 .chromakey = p64->chromakey,
0092 .clips = (uintptr_t)p64->clips,
0093 .clipcount = p64->clipcount,
0094 .bitmap = ptr_to_compat(p64->bitmap),
0095 .global_alpha = p64->global_alpha,
0096 };
0097
0098
0099 if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
0100 copy_to_user(&p32->clipcount, &w32.clipcount,
0101 sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
0102 return -EFAULT;
0103
0104 return 0;
0105 }
0106
0107 struct v4l2_format32 {
0108 __u32 type;
0109 union {
0110 struct v4l2_pix_format pix;
0111 struct v4l2_pix_format_mplane pix_mp;
0112 struct v4l2_window32 win;
0113 struct v4l2_vbi_format vbi;
0114 struct v4l2_sliced_vbi_format sliced;
0115 struct v4l2_sdr_format sdr;
0116 struct v4l2_meta_format meta;
0117 __u8 raw_data[200];
0118 } fmt;
0119 };
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 struct v4l2_create_buffers32 {
0135 __u32 index;
0136 __u32 count;
0137 __u32 memory;
0138 struct v4l2_format32 format;
0139 __u32 capabilities;
0140 __u32 flags;
0141 __u32 reserved[6];
0142 };
0143
0144 static int get_v4l2_format32(struct v4l2_format *p64,
0145 struct v4l2_format32 __user *p32)
0146 {
0147 if (get_user(p64->type, &p32->type))
0148 return -EFAULT;
0149
0150 switch (p64->type) {
0151 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
0152 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
0153 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
0154 sizeof(p64->fmt.pix)) ? -EFAULT : 0;
0155 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
0156 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
0157 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
0158 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
0159 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
0160 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
0161 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
0162 case V4L2_BUF_TYPE_VBI_CAPTURE:
0163 case V4L2_BUF_TYPE_VBI_OUTPUT:
0164 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
0165 sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
0166 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
0167 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
0168 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
0169 sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
0170 case V4L2_BUF_TYPE_SDR_CAPTURE:
0171 case V4L2_BUF_TYPE_SDR_OUTPUT:
0172 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
0173 sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
0174 case V4L2_BUF_TYPE_META_CAPTURE:
0175 case V4L2_BUF_TYPE_META_OUTPUT:
0176 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
0177 sizeof(p64->fmt.meta)) ? -EFAULT : 0;
0178 default:
0179 return -EINVAL;
0180 }
0181 }
0182
0183 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
0184 struct v4l2_create_buffers32 __user *p32)
0185 {
0186 if (copy_from_user(p64, p32,
0187 offsetof(struct v4l2_create_buffers32, format)))
0188 return -EFAULT;
0189 if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
0190 return -EFAULT;
0191 return get_v4l2_format32(&p64->format, &p32->format);
0192 }
0193
0194 static int put_v4l2_format32(struct v4l2_format *p64,
0195 struct v4l2_format32 __user *p32)
0196 {
0197 switch (p64->type) {
0198 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
0199 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
0200 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
0201 sizeof(p64->fmt.pix)) ? -EFAULT : 0;
0202 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
0203 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
0204 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
0205 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
0206 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
0207 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
0208 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
0209 case V4L2_BUF_TYPE_VBI_CAPTURE:
0210 case V4L2_BUF_TYPE_VBI_OUTPUT:
0211 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
0212 sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
0213 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
0214 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
0215 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
0216 sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
0217 case V4L2_BUF_TYPE_SDR_CAPTURE:
0218 case V4L2_BUF_TYPE_SDR_OUTPUT:
0219 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
0220 sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
0221 case V4L2_BUF_TYPE_META_CAPTURE:
0222 case V4L2_BUF_TYPE_META_OUTPUT:
0223 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
0224 sizeof(p64->fmt.meta)) ? -EFAULT : 0;
0225 default:
0226 return -EINVAL;
0227 }
0228 }
0229
0230 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
0231 struct v4l2_create_buffers32 __user *p32)
0232 {
0233 if (copy_to_user(p32, p64,
0234 offsetof(struct v4l2_create_buffers32, format)) ||
0235 put_user(p64->capabilities, &p32->capabilities) ||
0236 put_user(p64->flags, &p32->flags) ||
0237 copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
0238 return -EFAULT;
0239 return put_v4l2_format32(&p64->format, &p32->format);
0240 }
0241
0242 struct v4l2_standard32 {
0243 __u32 index;
0244 compat_u64 id;
0245 __u8 name[24];
0246 struct v4l2_fract frameperiod;
0247 __u32 framelines;
0248 __u32 reserved[4];
0249 };
0250
0251 static int get_v4l2_standard32(struct v4l2_standard *p64,
0252 struct v4l2_standard32 __user *p32)
0253 {
0254
0255 return get_user(p64->index, &p32->index);
0256 }
0257
0258 static int put_v4l2_standard32(struct v4l2_standard *p64,
0259 struct v4l2_standard32 __user *p32)
0260 {
0261 if (put_user(p64->index, &p32->index) ||
0262 put_user(p64->id, &p32->id) ||
0263 copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
0264 copy_to_user(&p32->frameperiod, &p64->frameperiod,
0265 sizeof(p32->frameperiod)) ||
0266 put_user(p64->framelines, &p32->framelines) ||
0267 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0268 return -EFAULT;
0269 return 0;
0270 }
0271
0272 struct v4l2_plane32 {
0273 __u32 bytesused;
0274 __u32 length;
0275 union {
0276 __u32 mem_offset;
0277 compat_long_t userptr;
0278 __s32 fd;
0279 } m;
0280 __u32 data_offset;
0281 __u32 reserved[11];
0282 };
0283
0284
0285
0286
0287
0288 struct v4l2_buffer32 {
0289 __u32 index;
0290 __u32 type;
0291 __u32 bytesused;
0292 __u32 flags;
0293 __u32 field;
0294 struct {
0295 compat_s64 tv_sec;
0296 compat_s64 tv_usec;
0297 } timestamp;
0298 struct v4l2_timecode timecode;
0299 __u32 sequence;
0300
0301
0302 __u32 memory;
0303 union {
0304 __u32 offset;
0305 compat_long_t userptr;
0306 compat_caddr_t planes;
0307 __s32 fd;
0308 } m;
0309 __u32 length;
0310 __u32 reserved2;
0311 __s32 request_fd;
0312 };
0313
0314 #ifdef CONFIG_COMPAT_32BIT_TIME
0315 struct v4l2_buffer32_time32 {
0316 __u32 index;
0317 __u32 type;
0318 __u32 bytesused;
0319 __u32 flags;
0320 __u32 field;
0321 struct old_timeval32 timestamp;
0322 struct v4l2_timecode timecode;
0323 __u32 sequence;
0324
0325
0326 __u32 memory;
0327 union {
0328 __u32 offset;
0329 compat_long_t userptr;
0330 compat_caddr_t planes;
0331 __s32 fd;
0332 } m;
0333 __u32 length;
0334 __u32 reserved2;
0335 __s32 request_fd;
0336 };
0337 #endif
0338
0339 static int get_v4l2_plane32(struct v4l2_plane *p64,
0340 struct v4l2_plane32 __user *p32,
0341 enum v4l2_memory memory)
0342 {
0343 struct v4l2_plane32 plane32;
0344 typeof(p64->m) m = {};
0345
0346 if (copy_from_user(&plane32, p32, sizeof(plane32)))
0347 return -EFAULT;
0348
0349 switch (memory) {
0350 case V4L2_MEMORY_MMAP:
0351 case V4L2_MEMORY_OVERLAY:
0352 m.mem_offset = plane32.m.mem_offset;
0353 break;
0354 case V4L2_MEMORY_USERPTR:
0355 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
0356 break;
0357 case V4L2_MEMORY_DMABUF:
0358 m.fd = plane32.m.fd;
0359 break;
0360 }
0361
0362 memset(p64, 0, sizeof(*p64));
0363 *p64 = (struct v4l2_plane) {
0364 .bytesused = plane32.bytesused,
0365 .length = plane32.length,
0366 .m = m,
0367 .data_offset = plane32.data_offset,
0368 };
0369
0370 return 0;
0371 }
0372
0373 static int put_v4l2_plane32(struct v4l2_plane *p64,
0374 struct v4l2_plane32 __user *p32,
0375 enum v4l2_memory memory)
0376 {
0377 struct v4l2_plane32 plane32;
0378
0379 memset(&plane32, 0, sizeof(plane32));
0380 plane32 = (struct v4l2_plane32) {
0381 .bytesused = p64->bytesused,
0382 .length = p64->length,
0383 .data_offset = p64->data_offset,
0384 };
0385
0386 switch (memory) {
0387 case V4L2_MEMORY_MMAP:
0388 case V4L2_MEMORY_OVERLAY:
0389 plane32.m.mem_offset = p64->m.mem_offset;
0390 break;
0391 case V4L2_MEMORY_USERPTR:
0392 plane32.m.userptr = (uintptr_t)(p64->m.userptr);
0393 break;
0394 case V4L2_MEMORY_DMABUF:
0395 plane32.m.fd = p64->m.fd;
0396 break;
0397 }
0398
0399 if (copy_to_user(p32, &plane32, sizeof(plane32)))
0400 return -EFAULT;
0401
0402 return 0;
0403 }
0404
0405 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
0406 struct v4l2_buffer32 __user *arg)
0407 {
0408 struct v4l2_buffer32 vb32;
0409
0410 if (copy_from_user(&vb32, arg, sizeof(vb32)))
0411 return -EFAULT;
0412
0413 memset(vb, 0, sizeof(*vb));
0414 *vb = (struct v4l2_buffer) {
0415 .index = vb32.index,
0416 .type = vb32.type,
0417 .bytesused = vb32.bytesused,
0418 .flags = vb32.flags,
0419 .field = vb32.field,
0420 .timestamp.tv_sec = vb32.timestamp.tv_sec,
0421 .timestamp.tv_usec = vb32.timestamp.tv_usec,
0422 .timecode = vb32.timecode,
0423 .sequence = vb32.sequence,
0424 .memory = vb32.memory,
0425 .m.offset = vb32.m.offset,
0426 .length = vb32.length,
0427 .request_fd = vb32.request_fd,
0428 };
0429
0430 switch (vb->memory) {
0431 case V4L2_MEMORY_MMAP:
0432 case V4L2_MEMORY_OVERLAY:
0433 vb->m.offset = vb32.m.offset;
0434 break;
0435 case V4L2_MEMORY_USERPTR:
0436 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
0437 break;
0438 case V4L2_MEMORY_DMABUF:
0439 vb->m.fd = vb32.m.fd;
0440 break;
0441 }
0442
0443 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0444 vb->m.planes = (void __force *)
0445 compat_ptr(vb32.m.planes);
0446
0447 return 0;
0448 }
0449
0450 #ifdef CONFIG_COMPAT_32BIT_TIME
0451 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
0452 struct v4l2_buffer32_time32 __user *arg)
0453 {
0454 struct v4l2_buffer32_time32 vb32;
0455
0456 if (copy_from_user(&vb32, arg, sizeof(vb32)))
0457 return -EFAULT;
0458
0459 *vb = (struct v4l2_buffer) {
0460 .index = vb32.index,
0461 .type = vb32.type,
0462 .bytesused = vb32.bytesused,
0463 .flags = vb32.flags,
0464 .field = vb32.field,
0465 .timestamp.tv_sec = vb32.timestamp.tv_sec,
0466 .timestamp.tv_usec = vb32.timestamp.tv_usec,
0467 .timecode = vb32.timecode,
0468 .sequence = vb32.sequence,
0469 .memory = vb32.memory,
0470 .m.offset = vb32.m.offset,
0471 .length = vb32.length,
0472 .request_fd = vb32.request_fd,
0473 };
0474 switch (vb->memory) {
0475 case V4L2_MEMORY_MMAP:
0476 case V4L2_MEMORY_OVERLAY:
0477 vb->m.offset = vb32.m.offset;
0478 break;
0479 case V4L2_MEMORY_USERPTR:
0480 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
0481 break;
0482 case V4L2_MEMORY_DMABUF:
0483 vb->m.fd = vb32.m.fd;
0484 break;
0485 }
0486
0487 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0488 vb->m.planes = (void __force *)
0489 compat_ptr(vb32.m.planes);
0490
0491 return 0;
0492 }
0493 #endif
0494
0495 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
0496 struct v4l2_buffer32 __user *arg)
0497 {
0498 struct v4l2_buffer32 vb32;
0499
0500 memset(&vb32, 0, sizeof(vb32));
0501 vb32 = (struct v4l2_buffer32) {
0502 .index = vb->index,
0503 .type = vb->type,
0504 .bytesused = vb->bytesused,
0505 .flags = vb->flags,
0506 .field = vb->field,
0507 .timestamp.tv_sec = vb->timestamp.tv_sec,
0508 .timestamp.tv_usec = vb->timestamp.tv_usec,
0509 .timecode = vb->timecode,
0510 .sequence = vb->sequence,
0511 .memory = vb->memory,
0512 .m.offset = vb->m.offset,
0513 .length = vb->length,
0514 .request_fd = vb->request_fd,
0515 };
0516
0517 switch (vb->memory) {
0518 case V4L2_MEMORY_MMAP:
0519 case V4L2_MEMORY_OVERLAY:
0520 vb32.m.offset = vb->m.offset;
0521 break;
0522 case V4L2_MEMORY_USERPTR:
0523 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
0524 break;
0525 case V4L2_MEMORY_DMABUF:
0526 vb32.m.fd = vb->m.fd;
0527 break;
0528 }
0529
0530 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0531 vb32.m.planes = (uintptr_t)vb->m.planes;
0532
0533 if (copy_to_user(arg, &vb32, sizeof(vb32)))
0534 return -EFAULT;
0535
0536 return 0;
0537 }
0538
0539 #ifdef CONFIG_COMPAT_32BIT_TIME
0540 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
0541 struct v4l2_buffer32_time32 __user *arg)
0542 {
0543 struct v4l2_buffer32_time32 vb32;
0544
0545 memset(&vb32, 0, sizeof(vb32));
0546 vb32 = (struct v4l2_buffer32_time32) {
0547 .index = vb->index,
0548 .type = vb->type,
0549 .bytesused = vb->bytesused,
0550 .flags = vb->flags,
0551 .field = vb->field,
0552 .timestamp.tv_sec = vb->timestamp.tv_sec,
0553 .timestamp.tv_usec = vb->timestamp.tv_usec,
0554 .timecode = vb->timecode,
0555 .sequence = vb->sequence,
0556 .memory = vb->memory,
0557 .m.offset = vb->m.offset,
0558 .length = vb->length,
0559 .request_fd = vb->request_fd,
0560 };
0561 switch (vb->memory) {
0562 case V4L2_MEMORY_MMAP:
0563 case V4L2_MEMORY_OVERLAY:
0564 vb32.m.offset = vb->m.offset;
0565 break;
0566 case V4L2_MEMORY_USERPTR:
0567 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
0568 break;
0569 case V4L2_MEMORY_DMABUF:
0570 vb32.m.fd = vb->m.fd;
0571 break;
0572 }
0573
0574 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0575 vb32.m.planes = (uintptr_t)vb->m.planes;
0576
0577 if (copy_to_user(arg, &vb32, sizeof(vb32)))
0578 return -EFAULT;
0579
0580 return 0;
0581 }
0582 #endif
0583
0584 struct v4l2_framebuffer32 {
0585 __u32 capability;
0586 __u32 flags;
0587 compat_caddr_t base;
0588 struct {
0589 __u32 width;
0590 __u32 height;
0591 __u32 pixelformat;
0592 __u32 field;
0593 __u32 bytesperline;
0594 __u32 sizeimage;
0595 __u32 colorspace;
0596 __u32 priv;
0597 } fmt;
0598 };
0599
0600 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
0601 struct v4l2_framebuffer32 __user *p32)
0602 {
0603 compat_caddr_t tmp;
0604
0605 if (get_user(tmp, &p32->base) ||
0606 get_user(p64->capability, &p32->capability) ||
0607 get_user(p64->flags, &p32->flags) ||
0608 copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
0609 return -EFAULT;
0610 p64->base = (void __force *)compat_ptr(tmp);
0611
0612 return 0;
0613 }
0614
0615 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
0616 struct v4l2_framebuffer32 __user *p32)
0617 {
0618 if (put_user((uintptr_t)p64->base, &p32->base) ||
0619 put_user(p64->capability, &p32->capability) ||
0620 put_user(p64->flags, &p32->flags) ||
0621 copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
0622 return -EFAULT;
0623
0624 return 0;
0625 }
0626
0627 struct v4l2_input32 {
0628 __u32 index;
0629 __u8 name[32];
0630 __u32 type;
0631 __u32 audioset;
0632 __u32 tuner;
0633 compat_u64 std;
0634 __u32 status;
0635 __u32 capabilities;
0636 __u32 reserved[3];
0637 };
0638
0639
0640
0641
0642
0643 static inline int get_v4l2_input32(struct v4l2_input *p64,
0644 struct v4l2_input32 __user *p32)
0645 {
0646 if (copy_from_user(p64, p32, sizeof(*p32)))
0647 return -EFAULT;
0648 return 0;
0649 }
0650
0651 static inline int put_v4l2_input32(struct v4l2_input *p64,
0652 struct v4l2_input32 __user *p32)
0653 {
0654 if (copy_to_user(p32, p64, sizeof(*p32)))
0655 return -EFAULT;
0656 return 0;
0657 }
0658
0659 struct v4l2_ext_controls32 {
0660 __u32 which;
0661 __u32 count;
0662 __u32 error_idx;
0663 __s32 request_fd;
0664 __u32 reserved[1];
0665 compat_caddr_t controls;
0666 };
0667
0668 struct v4l2_ext_control32 {
0669 __u32 id;
0670 __u32 size;
0671 __u32 reserved2[1];
0672 union {
0673 __s32 value;
0674 __s64 value64;
0675 compat_caddr_t string;
0676 };
0677 } __attribute__ ((packed));
0678
0679
0680 static inline bool ctrl_is_pointer(struct file *file, u32 id)
0681 {
0682 struct video_device *vdev = video_devdata(file);
0683 struct v4l2_fh *fh = NULL;
0684 struct v4l2_ctrl_handler *hdl = NULL;
0685 struct v4l2_query_ext_ctrl qec = { id };
0686 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
0687
0688 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
0689 fh = file->private_data;
0690
0691 if (fh && fh->ctrl_handler)
0692 hdl = fh->ctrl_handler;
0693 else if (vdev->ctrl_handler)
0694 hdl = vdev->ctrl_handler;
0695
0696 if (hdl) {
0697 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
0698
0699 return ctrl && ctrl->is_ptr;
0700 }
0701
0702 if (!ops || !ops->vidioc_query_ext_ctrl)
0703 return false;
0704
0705 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
0706 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
0707 }
0708
0709 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
0710 struct v4l2_ext_controls32 __user *p32)
0711 {
0712 struct v4l2_ext_controls32 ec32;
0713
0714 if (copy_from_user(&ec32, p32, sizeof(ec32)))
0715 return -EFAULT;
0716
0717 *p64 = (struct v4l2_ext_controls) {
0718 .which = ec32.which,
0719 .count = ec32.count,
0720 .error_idx = ec32.error_idx,
0721 .request_fd = ec32.request_fd,
0722 .reserved[0] = ec32.reserved[0],
0723 .controls = (void __force *)compat_ptr(ec32.controls),
0724 };
0725
0726 return 0;
0727 }
0728
0729 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
0730 struct v4l2_ext_controls32 __user *p32)
0731 {
0732 struct v4l2_ext_controls32 ec32;
0733
0734 memset(&ec32, 0, sizeof(ec32));
0735 ec32 = (struct v4l2_ext_controls32) {
0736 .which = p64->which,
0737 .count = p64->count,
0738 .error_idx = p64->error_idx,
0739 .request_fd = p64->request_fd,
0740 .reserved[0] = p64->reserved[0],
0741 .controls = (uintptr_t)p64->controls,
0742 };
0743
0744 if (copy_to_user(p32, &ec32, sizeof(ec32)))
0745 return -EFAULT;
0746
0747 return 0;
0748 }
0749
0750 #ifdef CONFIG_X86_64
0751
0752
0753
0754
0755 struct v4l2_event32 {
0756 __u32 type;
0757 union {
0758 compat_s64 value64;
0759 __u8 data[64];
0760 } u;
0761 __u32 pending;
0762 __u32 sequence;
0763 struct {
0764 compat_s64 tv_sec;
0765 compat_s64 tv_nsec;
0766 } timestamp;
0767 __u32 id;
0768 __u32 reserved[8];
0769 };
0770
0771 static int put_v4l2_event32(struct v4l2_event *p64,
0772 struct v4l2_event32 __user *p32)
0773 {
0774 if (put_user(p64->type, &p32->type) ||
0775 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
0776 put_user(p64->pending, &p32->pending) ||
0777 put_user(p64->sequence, &p32->sequence) ||
0778 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
0779 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
0780 put_user(p64->id, &p32->id) ||
0781 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0782 return -EFAULT;
0783 return 0;
0784 }
0785
0786 #endif
0787
0788 #ifdef CONFIG_COMPAT_32BIT_TIME
0789 struct v4l2_event32_time32 {
0790 __u32 type;
0791 union {
0792 compat_s64 value64;
0793 __u8 data[64];
0794 } u;
0795 __u32 pending;
0796 __u32 sequence;
0797 struct old_timespec32 timestamp;
0798 __u32 id;
0799 __u32 reserved[8];
0800 };
0801
0802 static int put_v4l2_event32_time32(struct v4l2_event *p64,
0803 struct v4l2_event32_time32 __user *p32)
0804 {
0805 if (put_user(p64->type, &p32->type) ||
0806 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
0807 put_user(p64->pending, &p32->pending) ||
0808 put_user(p64->sequence, &p32->sequence) ||
0809 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
0810 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
0811 put_user(p64->id, &p32->id) ||
0812 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0813 return -EFAULT;
0814 return 0;
0815 }
0816 #endif
0817
0818 struct v4l2_edid32 {
0819 __u32 pad;
0820 __u32 start_block;
0821 __u32 blocks;
0822 __u32 reserved[5];
0823 compat_caddr_t edid;
0824 };
0825
0826 static int get_v4l2_edid32(struct v4l2_edid *p64,
0827 struct v4l2_edid32 __user *p32)
0828 {
0829 compat_uptr_t edid;
0830
0831 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
0832 get_user(edid, &p32->edid))
0833 return -EFAULT;
0834
0835 p64->edid = (void __force *)compat_ptr(edid);
0836 return 0;
0837 }
0838
0839 static int put_v4l2_edid32(struct v4l2_edid *p64,
0840 struct v4l2_edid32 __user *p32)
0841 {
0842 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
0843 return -EFAULT;
0844 return 0;
0845 }
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
0856 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
0857 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
0858 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
0859 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
0860 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
0861 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
0862 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
0863 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
0864 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
0865 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
0866 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
0867 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
0868 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
0869 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
0870 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
0871 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
0872 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
0873
0874 #ifdef CONFIG_COMPAT_32BIT_TIME
0875 #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32)
0876 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32)
0877 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32)
0878 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32)
0879 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32)
0880 #endif
0881
0882 unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
0883 {
0884 switch (cmd) {
0885 case VIDIOC_G_FMT32:
0886 return VIDIOC_G_FMT;
0887 case VIDIOC_S_FMT32:
0888 return VIDIOC_S_FMT;
0889 case VIDIOC_TRY_FMT32:
0890 return VIDIOC_TRY_FMT;
0891 case VIDIOC_G_FBUF32:
0892 return VIDIOC_G_FBUF;
0893 case VIDIOC_S_FBUF32:
0894 return VIDIOC_S_FBUF;
0895 #ifdef CONFIG_COMPAT_32BIT_TIME
0896 case VIDIOC_QUERYBUF32_TIME32:
0897 return VIDIOC_QUERYBUF;
0898 case VIDIOC_QBUF32_TIME32:
0899 return VIDIOC_QBUF;
0900 case VIDIOC_DQBUF32_TIME32:
0901 return VIDIOC_DQBUF;
0902 case VIDIOC_PREPARE_BUF32_TIME32:
0903 return VIDIOC_PREPARE_BUF;
0904 #endif
0905 case VIDIOC_QUERYBUF32:
0906 return VIDIOC_QUERYBUF;
0907 case VIDIOC_QBUF32:
0908 return VIDIOC_QBUF;
0909 case VIDIOC_DQBUF32:
0910 return VIDIOC_DQBUF;
0911 case VIDIOC_CREATE_BUFS32:
0912 return VIDIOC_CREATE_BUFS;
0913 case VIDIOC_G_EXT_CTRLS32:
0914 return VIDIOC_G_EXT_CTRLS;
0915 case VIDIOC_S_EXT_CTRLS32:
0916 return VIDIOC_S_EXT_CTRLS;
0917 case VIDIOC_TRY_EXT_CTRLS32:
0918 return VIDIOC_TRY_EXT_CTRLS;
0919 case VIDIOC_PREPARE_BUF32:
0920 return VIDIOC_PREPARE_BUF;
0921 case VIDIOC_ENUMSTD32:
0922 return VIDIOC_ENUMSTD;
0923 case VIDIOC_ENUMINPUT32:
0924 return VIDIOC_ENUMINPUT;
0925 case VIDIOC_G_EDID32:
0926 return VIDIOC_G_EDID;
0927 case VIDIOC_S_EDID32:
0928 return VIDIOC_S_EDID;
0929 #ifdef CONFIG_X86_64
0930 case VIDIOC_DQEVENT32:
0931 return VIDIOC_DQEVENT;
0932 #endif
0933 #ifdef CONFIG_COMPAT_32BIT_TIME
0934 case VIDIOC_DQEVENT32_TIME32:
0935 return VIDIOC_DQEVENT;
0936 #endif
0937 }
0938 return cmd;
0939 }
0940
0941 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
0942 {
0943 switch (cmd) {
0944 case VIDIOC_G_FMT32:
0945 case VIDIOC_S_FMT32:
0946 case VIDIOC_TRY_FMT32:
0947 return get_v4l2_format32(parg, arg);
0948
0949 case VIDIOC_S_FBUF32:
0950 return get_v4l2_framebuffer32(parg, arg);
0951 #ifdef CONFIG_COMPAT_32BIT_TIME
0952 case VIDIOC_QUERYBUF32_TIME32:
0953 case VIDIOC_QBUF32_TIME32:
0954 case VIDIOC_DQBUF32_TIME32:
0955 case VIDIOC_PREPARE_BUF32_TIME32:
0956 return get_v4l2_buffer32_time32(parg, arg);
0957 #endif
0958 case VIDIOC_QUERYBUF32:
0959 case VIDIOC_QBUF32:
0960 case VIDIOC_DQBUF32:
0961 case VIDIOC_PREPARE_BUF32:
0962 return get_v4l2_buffer32(parg, arg);
0963
0964 case VIDIOC_G_EXT_CTRLS32:
0965 case VIDIOC_S_EXT_CTRLS32:
0966 case VIDIOC_TRY_EXT_CTRLS32:
0967 return get_v4l2_ext_controls32(parg, arg);
0968
0969 case VIDIOC_CREATE_BUFS32:
0970 return get_v4l2_create32(parg, arg);
0971
0972 case VIDIOC_ENUMSTD32:
0973 return get_v4l2_standard32(parg, arg);
0974
0975 case VIDIOC_ENUMINPUT32:
0976 return get_v4l2_input32(parg, arg);
0977
0978 case VIDIOC_G_EDID32:
0979 case VIDIOC_S_EDID32:
0980 return get_v4l2_edid32(parg, arg);
0981 }
0982 return 0;
0983 }
0984
0985 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
0986 {
0987 switch (cmd) {
0988 case VIDIOC_G_FMT32:
0989 case VIDIOC_S_FMT32:
0990 case VIDIOC_TRY_FMT32:
0991 return put_v4l2_format32(parg, arg);
0992
0993 case VIDIOC_G_FBUF32:
0994 return put_v4l2_framebuffer32(parg, arg);
0995 #ifdef CONFIG_COMPAT_32BIT_TIME
0996 case VIDIOC_QUERYBUF32_TIME32:
0997 case VIDIOC_QBUF32_TIME32:
0998 case VIDIOC_DQBUF32_TIME32:
0999 case VIDIOC_PREPARE_BUF32_TIME32:
1000 return put_v4l2_buffer32_time32(parg, arg);
1001 #endif
1002 case VIDIOC_QUERYBUF32:
1003 case VIDIOC_QBUF32:
1004 case VIDIOC_DQBUF32:
1005 case VIDIOC_PREPARE_BUF32:
1006 return put_v4l2_buffer32(parg, arg);
1007
1008 case VIDIOC_G_EXT_CTRLS32:
1009 case VIDIOC_S_EXT_CTRLS32:
1010 case VIDIOC_TRY_EXT_CTRLS32:
1011 return put_v4l2_ext_controls32(parg, arg);
1012
1013 case VIDIOC_CREATE_BUFS32:
1014 return put_v4l2_create32(parg, arg);
1015
1016 case VIDIOC_ENUMSTD32:
1017 return put_v4l2_standard32(parg, arg);
1018
1019 case VIDIOC_ENUMINPUT32:
1020 return put_v4l2_input32(parg, arg);
1021
1022 case VIDIOC_G_EDID32:
1023 case VIDIOC_S_EDID32:
1024 return put_v4l2_edid32(parg, arg);
1025 #ifdef CONFIG_X86_64
1026 case VIDIOC_DQEVENT32:
1027 return put_v4l2_event32(parg, arg);
1028 #endif
1029 #ifdef CONFIG_COMPAT_32BIT_TIME
1030 case VIDIOC_DQEVENT32_TIME32:
1031 return put_v4l2_event32_time32(parg, arg);
1032 #endif
1033 }
1034 return 0;
1035 }
1036
1037 int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1038 void __user *user_ptr, size_t array_size,
1039 unsigned int cmd, void *arg)
1040 {
1041 int err = 0;
1042
1043 memset(mbuf, 0, array_size);
1044
1045 switch (cmd) {
1046 case VIDIOC_G_FMT32:
1047 case VIDIOC_S_FMT32:
1048 case VIDIOC_TRY_FMT32: {
1049 struct v4l2_format *f64 = arg;
1050 struct v4l2_clip *c64 = mbuf;
1051 struct v4l2_clip32 __user *c32 = user_ptr;
1052 u32 clipcount = f64->fmt.win.clipcount;
1053
1054 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1055 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1056 clipcount == 0)
1057 return 0;
1058 if (clipcount > 2048)
1059 return -EINVAL;
1060 while (clipcount--) {
1061 if (copy_from_user(c64, c32, sizeof(c64->c)))
1062 return -EFAULT;
1063 c64->next = NULL;
1064 c64++;
1065 c32++;
1066 }
1067 break;
1068 }
1069 #ifdef CONFIG_COMPAT_32BIT_TIME
1070 case VIDIOC_QUERYBUF32_TIME32:
1071 case VIDIOC_QBUF32_TIME32:
1072 case VIDIOC_DQBUF32_TIME32:
1073 case VIDIOC_PREPARE_BUF32_TIME32:
1074 #endif
1075 case VIDIOC_QUERYBUF32:
1076 case VIDIOC_QBUF32:
1077 case VIDIOC_DQBUF32:
1078 case VIDIOC_PREPARE_BUF32: {
1079 struct v4l2_buffer *b64 = arg;
1080 struct v4l2_plane *p64 = mbuf;
1081 struct v4l2_plane32 __user *p32 = user_ptr;
1082
1083 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1084 u32 num_planes = b64->length;
1085
1086 if (num_planes == 0)
1087 return 0;
1088
1089 while (num_planes--) {
1090 err = get_v4l2_plane32(p64, p32, b64->memory);
1091 if (err)
1092 return err;
1093 ++p64;
1094 ++p32;
1095 }
1096 }
1097 break;
1098 }
1099 case VIDIOC_G_EXT_CTRLS32:
1100 case VIDIOC_S_EXT_CTRLS32:
1101 case VIDIOC_TRY_EXT_CTRLS32: {
1102 struct v4l2_ext_controls *ecs64 = arg;
1103 struct v4l2_ext_control *ec64 = mbuf;
1104 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1105 int n;
1106
1107 for (n = 0; n < ecs64->count; n++) {
1108 if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1109 return -EFAULT;
1110
1111 if (ctrl_is_pointer(file, ec64->id)) {
1112 compat_uptr_t p;
1113
1114 if (get_user(p, &ec32->string))
1115 return -EFAULT;
1116 ec64->string = compat_ptr(p);
1117 }
1118 ec32++;
1119 ec64++;
1120 }
1121 break;
1122 }
1123 default:
1124 if (copy_from_user(mbuf, user_ptr, array_size))
1125 err = -EFAULT;
1126 break;
1127 }
1128
1129 return err;
1130 }
1131
1132 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1133 void *mbuf, size_t array_size,
1134 unsigned int cmd, void *arg)
1135 {
1136 int err = 0;
1137
1138 switch (cmd) {
1139 case VIDIOC_G_FMT32:
1140 case VIDIOC_S_FMT32:
1141 case VIDIOC_TRY_FMT32: {
1142 struct v4l2_format *f64 = arg;
1143 struct v4l2_clip *c64 = mbuf;
1144 struct v4l2_clip32 __user *c32 = user_ptr;
1145 u32 clipcount = f64->fmt.win.clipcount;
1146
1147 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1148 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1149 clipcount == 0)
1150 return 0;
1151 if (clipcount > 2048)
1152 return -EINVAL;
1153 while (clipcount--) {
1154 if (copy_to_user(c32, c64, sizeof(c64->c)))
1155 return -EFAULT;
1156 c64++;
1157 c32++;
1158 }
1159 break;
1160 }
1161 #ifdef CONFIG_COMPAT_32BIT_TIME
1162 case VIDIOC_QUERYBUF32_TIME32:
1163 case VIDIOC_QBUF32_TIME32:
1164 case VIDIOC_DQBUF32_TIME32:
1165 case VIDIOC_PREPARE_BUF32_TIME32:
1166 #endif
1167 case VIDIOC_QUERYBUF32:
1168 case VIDIOC_QBUF32:
1169 case VIDIOC_DQBUF32:
1170 case VIDIOC_PREPARE_BUF32: {
1171 struct v4l2_buffer *b64 = arg;
1172 struct v4l2_plane *p64 = mbuf;
1173 struct v4l2_plane32 __user *p32 = user_ptr;
1174
1175 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1176 u32 num_planes = b64->length;
1177
1178 if (num_planes == 0)
1179 return 0;
1180
1181 while (num_planes--) {
1182 err = put_v4l2_plane32(p64, p32, b64->memory);
1183 if (err)
1184 return err;
1185 ++p64;
1186 ++p32;
1187 }
1188 }
1189 break;
1190 }
1191 case VIDIOC_G_EXT_CTRLS32:
1192 case VIDIOC_S_EXT_CTRLS32:
1193 case VIDIOC_TRY_EXT_CTRLS32: {
1194 struct v4l2_ext_controls *ecs64 = arg;
1195 struct v4l2_ext_control *ec64 = mbuf;
1196 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1197 int n;
1198
1199 for (n = 0; n < ecs64->count; n++) {
1200 unsigned int size = sizeof(*ec32);
1201
1202
1203
1204
1205
1206
1207 if (ctrl_is_pointer(file, ec64->id))
1208 size -= sizeof(ec32->value64);
1209
1210 if (copy_to_user(ec32, ec64, size))
1211 return -EFAULT;
1212
1213 ec32++;
1214 ec64++;
1215 }
1216 break;
1217 }
1218 default:
1219 if (copy_to_user(user_ptr, mbuf, array_size))
1220 err = -EFAULT;
1221 break;
1222 }
1223
1224 return err;
1225 }
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1242 {
1243 struct video_device *vdev = video_devdata(file);
1244 long ret = -ENOIOCTLCMD;
1245
1246 if (!file->f_op->unlocked_ioctl)
1247 return ret;
1248
1249 if (!video_is_registered(vdev))
1250 return -ENODEV;
1251
1252 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1253 ret = file->f_op->unlocked_ioctl(file, cmd,
1254 (unsigned long)compat_ptr(arg));
1255 else if (vdev->fops->compat_ioctl32)
1256 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1257
1258 if (ret == -ENOIOCTLCMD)
1259 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1260 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1261 return ret;
1262 }
1263 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);