1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls. 4 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de> 5 * 6 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) 7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 8 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs 9 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) 10 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) 11 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> 12 * 13 * These routines maintain argument size conversion between 32bit and 64bit 14 * ioctls. 15 */ 16 17 #include <linux/compat.h> 18 #include <linux/module.h> 19 #include <linux/videodev2.h> 20 #include <linux/v4l2-subdev.h> 21 #include <media/v4l2-dev.h> 22 #include <media/v4l2-fh.h> 23 #include <media/v4l2-ctrls.h> 24 #include <media/v4l2-ioctl.h> 25 26 /* 27 * Per-ioctl data copy handlers. 28 * 29 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine, 30 * where "v4l2_foo" is the name of the V4L2 struct. 31 * 32 * They basically get two __user pointers, one with a 32-bits struct that 33 * came from the userspace call and a 64-bits struct, also allocated as 34 * userspace, but filled internally by do_video_ioctl(). 35 * 36 * For ioctls that have pointers inside it, the functions will also 37 * receive an ancillary buffer with extra space, used to pass extra 38 * data to the routine. 39 */ 40 41 struct v4l2_clip32 { 42 struct v4l2_rect c; 43 compat_caddr_t next; 44 }; 45 46 struct v4l2_window32 { 47 struct v4l2_rect w; 48 __u32 field; /* enum v4l2_field */ 49 __u32 chromakey; 50 compat_caddr_t clips; /* actually struct v4l2_clip32 * */ 51 __u32 clipcount; 52 compat_caddr_t bitmap; 53 __u8 global_alpha; 54 }; 55 56 static int get_v4l2_window32(struct v4l2_window *p64, 57 struct v4l2_window32 __user *p32) 58 { 59 struct v4l2_window32 w32; 60 61 if (copy_from_user(&w32, p32, sizeof(w32))) 62 return -EFAULT; 63 64 *p64 = (struct v4l2_window) { 65 .w = w32.w, 66 .field = w32.field, 67 .chromakey = w32.chromakey, 68 .clips = (void __force *)compat_ptr(w32.clips), 69 .clipcount = w32.clipcount, 70 .bitmap = compat_ptr(w32.bitmap), 71 .global_alpha = w32.global_alpha, 72 }; 73 74 if (p64->clipcount > 2048) 75 return -EINVAL; 76 if (!p64->clipcount) 77 p64->clips = NULL; 78 79 return 0; 80 } 81 82 static int put_v4l2_window32(struct v4l2_window *p64, 83 struct v4l2_window32 __user *p32) 84 { 85 struct v4l2_window32 w32; 86 87 memset(&w32, 0, sizeof(w32)); 88 w32 = (struct v4l2_window32) { 89 .w = p64->w, 90 .field = p64->field, 91 .chromakey = p64->chromakey, 92 .clips = (uintptr_t)p64->clips, 93 .clipcount = p64->clipcount, 94 .bitmap = ptr_to_compat(p64->bitmap), 95 .global_alpha = p64->global_alpha, 96 }; 97 98 /* copy everything except the clips pointer */ 99 if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) || 100 copy_to_user(&p32->clipcount, &w32.clipcount, 101 sizeof(w32) - offsetof(struct v4l2_window32, clipcount))) 102 return -EFAULT; 103 104 return 0; 105 } 106 107 struct v4l2_format32 { 108 __u32 type; /* enum v4l2_buf_type */ 109 union { 110 struct v4l2_pix_format pix; 111 struct v4l2_pix_format_mplane pix_mp; 112 struct v4l2_window32 win; 113 struct v4l2_vbi_format vbi; 114 struct v4l2_sliced_vbi_format sliced; 115 struct v4l2_sdr_format sdr; 116 struct v4l2_meta_format meta; 117 __u8 raw_data[200]; /* user-defined */ 118 } fmt; 119 }; 120 121 /** 122 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument 123 * @index: on return, index of the first created buffer 124 * @count: entry: number of requested buffers, 125 * return: number of created buffers 126 * @memory: buffer memory type 127 * @format: frame format, for which buffers are requested 128 * @capabilities: capabilities of this buffer type. 129 * @flags: additional buffer management attributes (ignored unless the 130 * queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and 131 * configured for MMAP streaming I/O). 132 * @reserved: future extensions 133 */ 134 struct v4l2_create_buffers32 { 135 __u32 index; 136 __u32 count; 137 __u32 memory; /* enum v4l2_memory */ 138 struct v4l2_format32 format; 139 __u32 capabilities; 140 __u32 flags; 141 __u32 reserved[6]; 142 }; 143 144 static int get_v4l2_format32(struct v4l2_format *p64, 145 struct v4l2_format32 __user *p32) 146 { 147 if (get_user(p64->type, &p32->type)) 148 return -EFAULT; 149 150 switch (p64->type) { 151 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 152 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 153 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix, 154 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 155 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 156 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 157 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp, 158 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 159 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 160 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 161 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 162 case V4L2_BUF_TYPE_VBI_CAPTURE: 163 case V4L2_BUF_TYPE_VBI_OUTPUT: 164 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi, 165 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 166 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 167 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 168 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced, 169 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 170 case V4L2_BUF_TYPE_SDR_CAPTURE: 171 case V4L2_BUF_TYPE_SDR_OUTPUT: 172 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr, 173 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 174 case V4L2_BUF_TYPE_META_CAPTURE: 175 case V4L2_BUF_TYPE_META_OUTPUT: 176 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta, 177 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 178 default: 179 return -EINVAL; 180 } 181 } 182 183 static int get_v4l2_create32(struct v4l2_create_buffers *p64, 184 struct v4l2_create_buffers32 __user *p32) 185 { 186 if (copy_from_user(p64, p32, 187 offsetof(struct v4l2_create_buffers32, format))) 188 return -EFAULT; 189 if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags))) 190 return -EFAULT; 191 return get_v4l2_format32(&p64->format, &p32->format); 192 } 193 194 static int put_v4l2_format32(struct v4l2_format *p64, 195 struct v4l2_format32 __user *p32) 196 { 197 switch (p64->type) { 198 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 199 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 200 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix, 201 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 202 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 203 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 204 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp, 205 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 206 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 207 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 208 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 209 case V4L2_BUF_TYPE_VBI_CAPTURE: 210 case V4L2_BUF_TYPE_VBI_OUTPUT: 211 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi, 212 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 213 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 214 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 215 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced, 216 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 217 case V4L2_BUF_TYPE_SDR_CAPTURE: 218 case V4L2_BUF_TYPE_SDR_OUTPUT: 219 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr, 220 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 221 case V4L2_BUF_TYPE_META_CAPTURE: 222 case V4L2_BUF_TYPE_META_OUTPUT: 223 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta, 224 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 225 default: 226 return -EINVAL; 227 } 228 } 229 230 static int put_v4l2_create32(struct v4l2_create_buffers *p64, 231 struct v4l2_create_buffers32 __user *p32) 232 { 233 if (copy_to_user(p32, p64, 234 offsetof(struct v4l2_create_buffers32, format)) || 235 put_user(p64->capabilities, &p32->capabilities) || 236 put_user(p64->flags, &p32->flags) || 237 copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved))) 238 return -EFAULT; 239 return put_v4l2_format32(&p64->format, &p32->format); 240 } 241 242 struct v4l2_standard32 { 243 __u32 index; 244 compat_u64 id; 245 __u8 name[24]; 246 struct v4l2_fract frameperiod; /* Frames, not fields */ 247 __u32 framelines; 248 __u32 reserved[4]; 249 }; 250 251 static int get_v4l2_standard32(struct v4l2_standard *p64, 252 struct v4l2_standard32 __user *p32) 253 { 254 /* other fields are not set by the user, nor used by the driver */ 255 return get_user(p64->index, &p32->index); 256 } 257 258 static int put_v4l2_standard32(struct v4l2_standard *p64, 259 struct v4l2_standard32 __user *p32) 260 { 261 if (put_user(p64->index, &p32->index) || 262 put_user(p64->id, &p32->id) || 263 copy_to_user(p32->name, p64->name, sizeof(p32->name)) || 264 copy_to_user(&p32->frameperiod, &p64->frameperiod, 265 sizeof(p32->frameperiod)) || 266 put_user(p64->framelines, &p32->framelines) || 267 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 268 return -EFAULT; 269 return 0; 270 } 271 272 struct v4l2_plane32 { 273 __u32 bytesused; 274 __u32 length; 275 union { 276 __u32 mem_offset; 277 compat_long_t userptr; 278 __s32 fd; 279 } m; 280 __u32 data_offset; 281 __u32 reserved[11]; 282 }; 283 284 /* 285 * This is correct for all architectures including i386, but not x32, 286 * which has different alignment requirements for timestamp 287 */ 288 struct v4l2_buffer32 { 289 __u32 index; 290 __u32 type; /* enum v4l2_buf_type */ 291 __u32 bytesused; 292 __u32 flags; 293 __u32 field; /* enum v4l2_field */ 294 struct { 295 compat_s64 tv_sec; 296 compat_s64 tv_usec; 297 } timestamp; 298 struct v4l2_timecode timecode; 299 __u32 sequence; 300 301 /* memory location */ 302 __u32 memory; /* enum v4l2_memory */ 303 union { 304 __u32 offset; 305 compat_long_t userptr; 306 compat_caddr_t planes; 307 __s32 fd; 308 } m; 309 __u32 length; 310 __u32 reserved2; 311 __s32 request_fd; 312 }; 313 314 #ifdef CONFIG_COMPAT_32BIT_TIME 315 struct v4l2_buffer32_time32 { 316 __u32 index; 317 __u32 type; /* enum v4l2_buf_type */ 318 __u32 bytesused; 319 __u32 flags; 320 __u32 field; /* enum v4l2_field */ 321 struct old_timeval32 timestamp; 322 struct v4l2_timecode timecode; 323 __u32 sequence; 324 325 /* memory location */ 326 __u32 memory; /* enum v4l2_memory */ 327 union { 328 __u32 offset; 329 compat_long_t userptr; 330 compat_caddr_t planes; 331 __s32 fd; 332 } m; 333 __u32 length; 334 __u32 reserved2; 335 __s32 request_fd; 336 }; 337 #endif 338 339 static int get_v4l2_plane32(struct v4l2_plane *p64, 340 struct v4l2_plane32 __user *p32, 341 enum v4l2_memory memory) 342 { 343 struct v4l2_plane32 plane32; 344 typeof(p64->m) m = {}; 345 346 if (copy_from_user(&plane32, p32, sizeof(plane32))) 347 return -EFAULT; 348 349 switch (memory) { 350 case V4L2_MEMORY_MMAP: 351 case V4L2_MEMORY_OVERLAY: 352 m.mem_offset = plane32.m.mem_offset; 353 break; 354 case V4L2_MEMORY_USERPTR: 355 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr); 356 break; 357 case V4L2_MEMORY_DMABUF: 358 m.fd = plane32.m.fd; 359 break; 360 } 361 362 memset(p64, 0, sizeof(*p64)); 363 *p64 = (struct v4l2_plane) { 364 .bytesused = plane32.bytesused, 365 .length = plane32.length, 366 .m = m, 367 .data_offset = plane32.data_offset, 368 }; 369 370 return 0; 371 } 372 373 static int put_v4l2_plane32(struct v4l2_plane *p64, 374 struct v4l2_plane32 __user *p32, 375 enum v4l2_memory memory) 376 { 377 struct v4l2_plane32 plane32; 378 379 memset(&plane32, 0, sizeof(plane32)); 380 plane32 = (struct v4l2_plane32) { 381 .bytesused = p64->bytesused, 382 .length = p64->length, 383 .data_offset = p64->data_offset, 384 }; 385 386 switch (memory) { 387 case V4L2_MEMORY_MMAP: 388 case V4L2_MEMORY_OVERLAY: 389 plane32.m.mem_offset = p64->m.mem_offset; 390 break; 391 case V4L2_MEMORY_USERPTR: 392 plane32.m.userptr = (uintptr_t)(p64->m.userptr); 393 break; 394 case V4L2_MEMORY_DMABUF: 395 plane32.m.fd = p64->m.fd; 396 break; 397 } 398 399 if (copy_to_user(p32, &plane32, sizeof(plane32))) 400 return -EFAULT; 401 402 return 0; 403 } 404 405 static int get_v4l2_buffer32(struct v4l2_buffer *vb, 406 struct v4l2_buffer32 __user *arg) 407 { 408 struct v4l2_buffer32 vb32; 409 410 if (copy_from_user(&vb32, arg, sizeof(vb32))) 411 return -EFAULT; 412 413 memset(vb, 0, sizeof(*vb)); 414 *vb = (struct v4l2_buffer) { 415 .index = vb32.index, 416 .type = vb32.type, 417 .bytesused = vb32.bytesused, 418 .flags = vb32.flags, 419 .field = vb32.field, 420 .timestamp.tv_sec = vb32.timestamp.tv_sec, 421 .timestamp.tv_usec = vb32.timestamp.tv_usec, 422 .timecode = vb32.timecode, 423 .sequence = vb32.sequence, 424 .memory = vb32.memory, 425 .m.offset = vb32.m.offset, 426 .length = vb32.length, 427 .request_fd = vb32.request_fd, 428 }; 429 430 switch (vb->memory) { 431 case V4L2_MEMORY_MMAP: 432 case V4L2_MEMORY_OVERLAY: 433 vb->m.offset = vb32.m.offset; 434 break; 435 case V4L2_MEMORY_USERPTR: 436 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 437 break; 438 case V4L2_MEMORY_DMABUF: 439 vb->m.fd = vb32.m.fd; 440 break; 441 } 442 443 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 444 vb->m.planes = (void __force *) 445 compat_ptr(vb32.m.planes); 446 447 return 0; 448 } 449 450 #ifdef CONFIG_COMPAT_32BIT_TIME 451 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb, 452 struct v4l2_buffer32_time32 __user *arg) 453 { 454 struct v4l2_buffer32_time32 vb32; 455 456 if (copy_from_user(&vb32, arg, sizeof(vb32))) 457 return -EFAULT; 458 459 *vb = (struct v4l2_buffer) { 460 .index = vb32.index, 461 .type = vb32.type, 462 .bytesused = vb32.bytesused, 463 .flags = vb32.flags, 464 .field = vb32.field, 465 .timestamp.tv_sec = vb32.timestamp.tv_sec, 466 .timestamp.tv_usec = vb32.timestamp.tv_usec, 467 .timecode = vb32.timecode, 468 .sequence = vb32.sequence, 469 .memory = vb32.memory, 470 .m.offset = vb32.m.offset, 471 .length = vb32.length, 472 .request_fd = vb32.request_fd, 473 }; 474 switch (vb->memory) { 475 case V4L2_MEMORY_MMAP: 476 case V4L2_MEMORY_OVERLAY: 477 vb->m.offset = vb32.m.offset; 478 break; 479 case V4L2_MEMORY_USERPTR: 480 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 481 break; 482 case V4L2_MEMORY_DMABUF: 483 vb->m.fd = vb32.m.fd; 484 break; 485 } 486 487 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 488 vb->m.planes = (void __force *) 489 compat_ptr(vb32.m.planes); 490 491 return 0; 492 } 493 #endif 494 495 static int put_v4l2_buffer32(struct v4l2_buffer *vb, 496 struct v4l2_buffer32 __user *arg) 497 { 498 struct v4l2_buffer32 vb32; 499 500 memset(&vb32, 0, sizeof(vb32)); 501 vb32 = (struct v4l2_buffer32) { 502 .index = vb->index, 503 .type = vb->type, 504 .bytesused = vb->bytesused, 505 .flags = vb->flags, 506 .field = vb->field, 507 .timestamp.tv_sec = vb->timestamp.tv_sec, 508 .timestamp.tv_usec = vb->timestamp.tv_usec, 509 .timecode = vb->timecode, 510 .sequence = vb->sequence, 511 .memory = vb->memory, 512 .m.offset = vb->m.offset, 513 .length = vb->length, 514 .request_fd = vb->request_fd, 515 }; 516 517 switch (vb->memory) { 518 case V4L2_MEMORY_MMAP: 519 case V4L2_MEMORY_OVERLAY: 520 vb32.m.offset = vb->m.offset; 521 break; 522 case V4L2_MEMORY_USERPTR: 523 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 524 break; 525 case V4L2_MEMORY_DMABUF: 526 vb32.m.fd = vb->m.fd; 527 break; 528 } 529 530 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 531 vb32.m.planes = (uintptr_t)vb->m.planes; 532 533 if (copy_to_user(arg, &vb32, sizeof(vb32))) 534 return -EFAULT; 535 536 return 0; 537 } 538 539 #ifdef CONFIG_COMPAT_32BIT_TIME 540 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb, 541 struct v4l2_buffer32_time32 __user *arg) 542 { 543 struct v4l2_buffer32_time32 vb32; 544 545 memset(&vb32, 0, sizeof(vb32)); 546 vb32 = (struct v4l2_buffer32_time32) { 547 .index = vb->index, 548 .type = vb->type, 549 .bytesused = vb->bytesused, 550 .flags = vb->flags, 551 .field = vb->field, 552 .timestamp.tv_sec = vb->timestamp.tv_sec, 553 .timestamp.tv_usec = vb->timestamp.tv_usec, 554 .timecode = vb->timecode, 555 .sequence = vb->sequence, 556 .memory = vb->memory, 557 .m.offset = vb->m.offset, 558 .length = vb->length, 559 .request_fd = vb->request_fd, 560 }; 561 switch (vb->memory) { 562 case V4L2_MEMORY_MMAP: 563 case V4L2_MEMORY_OVERLAY: 564 vb32.m.offset = vb->m.offset; 565 break; 566 case V4L2_MEMORY_USERPTR: 567 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 568 break; 569 case V4L2_MEMORY_DMABUF: 570 vb32.m.fd = vb->m.fd; 571 break; 572 } 573 574 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 575 vb32.m.planes = (uintptr_t)vb->m.planes; 576 577 if (copy_to_user(arg, &vb32, sizeof(vb32))) 578 return -EFAULT; 579 580 return 0; 581 } 582 #endif 583 584 struct v4l2_framebuffer32 { 585 __u32 capability; 586 __u32 flags; 587 compat_caddr_t base; 588 struct { 589 __u32 width; 590 __u32 height; 591 __u32 pixelformat; 592 __u32 field; 593 __u32 bytesperline; 594 __u32 sizeimage; 595 __u32 colorspace; 596 __u32 priv; 597 } fmt; 598 }; 599 600 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 601 struct v4l2_framebuffer32 __user *p32) 602 { 603 compat_caddr_t tmp; 604 605 if (get_user(tmp, &p32->base) || 606 get_user(p64->capability, &p32->capability) || 607 get_user(p64->flags, &p32->flags) || 608 copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt))) 609 return -EFAULT; 610 p64->base = (void __force *)compat_ptr(tmp); 611 612 return 0; 613 } 614 615 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 616 struct v4l2_framebuffer32 __user *p32) 617 { 618 if (put_user((uintptr_t)p64->base, &p32->base) || 619 put_user(p64->capability, &p32->capability) || 620 put_user(p64->flags, &p32->flags) || 621 copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt))) 622 return -EFAULT; 623 624 return 0; 625 } 626 627 struct v4l2_input32 { 628 __u32 index; /* Which input */ 629 __u8 name[32]; /* Label */ 630 __u32 type; /* Type of input */ 631 __u32 audioset; /* Associated audios (bitfield) */ 632 __u32 tuner; /* Associated tuner */ 633 compat_u64 std; 634 __u32 status; 635 __u32 capabilities; 636 __u32 reserved[3]; 637 }; 638 639 /* 640 * The 64-bit v4l2_input struct has extra padding at the end of the struct. 641 * Otherwise it is identical to the 32-bit version. 642 */ 643 static inline int get_v4l2_input32(struct v4l2_input *p64, 644 struct v4l2_input32 __user *p32) 645 { 646 if (copy_from_user(p64, p32, sizeof(*p32))) 647 return -EFAULT; 648 return 0; 649 } 650 651 static inline int put_v4l2_input32(struct v4l2_input *p64, 652 struct v4l2_input32 __user *p32) 653 { 654 if (copy_to_user(p32, p64, sizeof(*p32))) 655 return -EFAULT; 656 return 0; 657 } 658 659 struct v4l2_ext_controls32 { 660 __u32 which; 661 __u32 count; 662 __u32 error_idx; 663 __s32 request_fd; 664 __u32 reserved[1]; 665 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 666 }; 667 668 struct v4l2_ext_control32 { 669 __u32 id; 670 __u32 size; 671 __u32 reserved2[1]; 672 union { 673 __s32 value; 674 __s64 value64; 675 compat_caddr_t string; /* actually char * */ 676 }; 677 } __attribute__ ((packed)); 678 679 /* Return true if this control is a pointer type. */ 680 static inline bool ctrl_is_pointer(struct file *file, u32 id) 681 { 682 struct video_device *vdev = video_devdata(file); 683 struct v4l2_fh *fh = NULL; 684 struct v4l2_ctrl_handler *hdl = NULL; 685 struct v4l2_query_ext_ctrl qec = { id }; 686 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; 687 688 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) 689 fh = file->private_data; 690 691 if (fh && fh->ctrl_handler) 692 hdl = fh->ctrl_handler; 693 else if (vdev->ctrl_handler) 694 hdl = vdev->ctrl_handler; 695 696 if (hdl) { 697 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); 698 699 return ctrl && ctrl->is_ptr; 700 } 701 702 if (!ops || !ops->vidioc_query_ext_ctrl) 703 return false; 704 705 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && 706 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); 707 } 708 709 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 710 struct v4l2_ext_controls32 __user *p32) 711 { 712 struct v4l2_ext_controls32 ec32; 713 714 if (copy_from_user(&ec32, p32, sizeof(ec32))) 715 return -EFAULT; 716 717 *p64 = (struct v4l2_ext_controls) { 718 .which = ec32.which, 719 .count = ec32.count, 720 .error_idx = ec32.error_idx, 721 .request_fd = ec32.request_fd, 722 .reserved[0] = ec32.reserved[0], 723 .controls = (void __force *)compat_ptr(ec32.controls), 724 }; 725 726 return 0; 727 } 728 729 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 730 struct v4l2_ext_controls32 __user *p32) 731 { 732 struct v4l2_ext_controls32 ec32; 733 734 memset(&ec32, 0, sizeof(ec32)); 735 ec32 = (struct v4l2_ext_controls32) { 736 .which = p64->which, 737 .count = p64->count, 738 .error_idx = p64->error_idx, 739 .request_fd = p64->request_fd, 740 .reserved[0] = p64->reserved[0], 741 .controls = (uintptr_t)p64->controls, 742 }; 743 744 if (copy_to_user(p32, &ec32, sizeof(ec32))) 745 return -EFAULT; 746 747 return 0; 748 } 749 750 #ifdef CONFIG_X86_64 751 /* 752 * x86 is the only compat architecture with different struct alignment 753 * between 32-bit and 64-bit tasks. 754 * 755 * On all other architectures, v4l2_event32 and v4l2_event32_time32 are 756 * the same as v4l2_event and v4l2_event_time32, so we can use the native 757 * handlers, converting v4l2_event to v4l2_event_time32 if necessary. 758 */ 759 struct v4l2_event32 { 760 __u32 type; 761 union { 762 compat_s64 value64; 763 __u8 data[64]; 764 } u; 765 __u32 pending; 766 __u32 sequence; 767 struct { 768 compat_s64 tv_sec; 769 compat_s64 tv_nsec; 770 } timestamp; 771 __u32 id; 772 __u32 reserved[8]; 773 }; 774 775 #ifdef CONFIG_COMPAT_32BIT_TIME 776 struct v4l2_event32_time32 { 777 __u32 type; 778 union { 779 compat_s64 value64; 780 __u8 data[64]; 781 } u; 782 __u32 pending; 783 __u32 sequence; 784 struct old_timespec32 timestamp; 785 __u32 id; 786 __u32 reserved[8]; 787 }; 788 #endif 789 790 static int put_v4l2_event32(struct v4l2_event *p64, 791 struct v4l2_event32 __user *p32) 792 { 793 if (put_user(p64->type, &p32->type) || 794 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 795 put_user(p64->pending, &p32->pending) || 796 put_user(p64->sequence, &p32->sequence) || 797 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 798 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 799 put_user(p64->id, &p32->id) || 800 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 801 return -EFAULT; 802 return 0; 803 } 804 805 #ifdef CONFIG_COMPAT_32BIT_TIME 806 static int put_v4l2_event32_time32(struct v4l2_event *p64, 807 struct v4l2_event32_time32 __user *p32) 808 { 809 if (put_user(p64->type, &p32->type) || 810 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 811 put_user(p64->pending, &p32->pending) || 812 put_user(p64->sequence, &p32->sequence) || 813 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 814 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 815 put_user(p64->id, &p32->id) || 816 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 817 return -EFAULT; 818 return 0; 819 } 820 #endif 821 #endif 822 823 struct v4l2_edid32 { 824 __u32 pad; 825 __u32 start_block; 826 __u32 blocks; 827 __u32 reserved[5]; 828 compat_caddr_t edid; 829 }; 830 831 static int get_v4l2_edid32(struct v4l2_edid *p64, 832 struct v4l2_edid32 __user *p32) 833 { 834 compat_uptr_t edid; 835 836 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) || 837 get_user(edid, &p32->edid)) 838 return -EFAULT; 839 840 p64->edid = (void __force *)compat_ptr(edid); 841 return 0; 842 } 843 844 static int put_v4l2_edid32(struct v4l2_edid *p64, 845 struct v4l2_edid32 __user *p32) 846 { 847 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid))) 848 return -EFAULT; 849 return 0; 850 } 851 852 /* 853 * List of ioctls that require 32-bits/64-bits conversion 854 * 855 * The V4L2 ioctls that aren't listed there don't have pointer arguments 856 * and the struct size is identical for both 32 and 64 bits versions, so 857 * they don't need translations. 858 */ 859 860 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 861 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 862 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 863 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 864 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 865 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 866 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 867 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 868 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 869 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) 870 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) 871 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 872 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 873 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 874 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 875 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 876 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 877 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 878 879 #ifdef CONFIG_COMPAT_32BIT_TIME 880 #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) 881 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) 882 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) 883 #ifdef CONFIG_X86_64 884 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) 885 #endif 886 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) 887 #endif 888 889 unsigned int v4l2_compat_translate_cmd(unsigned int cmd) 890 { 891 switch (cmd) { 892 case VIDIOC_G_FMT32: 893 return VIDIOC_G_FMT; 894 case VIDIOC_S_FMT32: 895 return VIDIOC_S_FMT; 896 case VIDIOC_TRY_FMT32: 897 return VIDIOC_TRY_FMT; 898 case VIDIOC_G_FBUF32: 899 return VIDIOC_G_FBUF; 900 case VIDIOC_S_FBUF32: 901 return VIDIOC_S_FBUF; 902 #ifdef CONFIG_COMPAT_32BIT_TIME 903 case VIDIOC_QUERYBUF32_TIME32: 904 return VIDIOC_QUERYBUF; 905 case VIDIOC_QBUF32_TIME32: 906 return VIDIOC_QBUF; 907 case VIDIOC_DQBUF32_TIME32: 908 return VIDIOC_DQBUF; 909 case VIDIOC_PREPARE_BUF32_TIME32: 910 return VIDIOC_PREPARE_BUF; 911 #endif 912 case VIDIOC_QUERYBUF32: 913 return VIDIOC_QUERYBUF; 914 case VIDIOC_QBUF32: 915 return VIDIOC_QBUF; 916 case VIDIOC_DQBUF32: 917 return VIDIOC_DQBUF; 918 case VIDIOC_CREATE_BUFS32: 919 return VIDIOC_CREATE_BUFS; 920 case VIDIOC_G_EXT_CTRLS32: 921 return VIDIOC_G_EXT_CTRLS; 922 case VIDIOC_S_EXT_CTRLS32: 923 return VIDIOC_S_EXT_CTRLS; 924 case VIDIOC_TRY_EXT_CTRLS32: 925 return VIDIOC_TRY_EXT_CTRLS; 926 case VIDIOC_PREPARE_BUF32: 927 return VIDIOC_PREPARE_BUF; 928 case VIDIOC_ENUMSTD32: 929 return VIDIOC_ENUMSTD; 930 case VIDIOC_ENUMINPUT32: 931 return VIDIOC_ENUMINPUT; 932 case VIDIOC_G_EDID32: 933 return VIDIOC_G_EDID; 934 case VIDIOC_S_EDID32: 935 return VIDIOC_S_EDID; 936 #ifdef CONFIG_X86_64 937 case VIDIOC_DQEVENT32: 938 return VIDIOC_DQEVENT; 939 #ifdef CONFIG_COMPAT_32BIT_TIME 940 case VIDIOC_DQEVENT32_TIME32: 941 return VIDIOC_DQEVENT; 942 #endif 943 #endif 944 } 945 return cmd; 946 } 947 948 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd) 949 { 950 switch (cmd) { 951 case VIDIOC_G_FMT32: 952 case VIDIOC_S_FMT32: 953 case VIDIOC_TRY_FMT32: 954 return get_v4l2_format32(parg, arg); 955 956 case VIDIOC_S_FBUF32: 957 return get_v4l2_framebuffer32(parg, arg); 958 #ifdef CONFIG_COMPAT_32BIT_TIME 959 case VIDIOC_QUERYBUF32_TIME32: 960 case VIDIOC_QBUF32_TIME32: 961 case VIDIOC_DQBUF32_TIME32: 962 case VIDIOC_PREPARE_BUF32_TIME32: 963 return get_v4l2_buffer32_time32(parg, arg); 964 #endif 965 case VIDIOC_QUERYBUF32: 966 case VIDIOC_QBUF32: 967 case VIDIOC_DQBUF32: 968 case VIDIOC_PREPARE_BUF32: 969 return get_v4l2_buffer32(parg, arg); 970 971 case VIDIOC_G_EXT_CTRLS32: 972 case VIDIOC_S_EXT_CTRLS32: 973 case VIDIOC_TRY_EXT_CTRLS32: 974 return get_v4l2_ext_controls32(parg, arg); 975 976 case VIDIOC_CREATE_BUFS32: 977 return get_v4l2_create32(parg, arg); 978 979 case VIDIOC_ENUMSTD32: 980 return get_v4l2_standard32(parg, arg); 981 982 case VIDIOC_ENUMINPUT32: 983 return get_v4l2_input32(parg, arg); 984 985 case VIDIOC_G_EDID32: 986 case VIDIOC_S_EDID32: 987 return get_v4l2_edid32(parg, arg); 988 } 989 return 0; 990 } 991 992 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) 993 { 994 switch (cmd) { 995 case VIDIOC_G_FMT32: 996 case VIDIOC_S_FMT32: 997 case VIDIOC_TRY_FMT32: 998 return put_v4l2_format32(parg, arg); 999 1000 case VIDIOC_G_FBUF32: 1001 return put_v4l2_framebuffer32(parg, arg); 1002 #ifdef CONFIG_COMPAT_32BIT_TIME 1003 case VIDIOC_QUERYBUF32_TIME32: 1004 case VIDIOC_QBUF32_TIME32: 1005 case VIDIOC_DQBUF32_TIME32: 1006 case VIDIOC_PREPARE_BUF32_TIME32: 1007 return put_v4l2_buffer32_time32(parg, arg); 1008 #endif 1009 case VIDIOC_QUERYBUF32: 1010 case VIDIOC_QBUF32: 1011 case VIDIOC_DQBUF32: 1012 case VIDIOC_PREPARE_BUF32: 1013 return put_v4l2_buffer32(parg, arg); 1014 1015 case VIDIOC_G_EXT_CTRLS32: 1016 case VIDIOC_S_EXT_CTRLS32: 1017 case VIDIOC_TRY_EXT_CTRLS32: 1018 return put_v4l2_ext_controls32(parg, arg); 1019 1020 case VIDIOC_CREATE_BUFS32: 1021 return put_v4l2_create32(parg, arg); 1022 1023 case VIDIOC_ENUMSTD32: 1024 return put_v4l2_standard32(parg, arg); 1025 1026 case VIDIOC_ENUMINPUT32: 1027 return put_v4l2_input32(parg, arg); 1028 1029 case VIDIOC_G_EDID32: 1030 case VIDIOC_S_EDID32: 1031 return put_v4l2_edid32(parg, arg); 1032 #ifdef CONFIG_X86_64 1033 case VIDIOC_DQEVENT32: 1034 return put_v4l2_event32(parg, arg); 1035 #ifdef CONFIG_COMPAT_32BIT_TIME 1036 case VIDIOC_DQEVENT32_TIME32: 1037 return put_v4l2_event32_time32(parg, arg); 1038 #endif 1039 #endif 1040 } 1041 return 0; 1042 } 1043 1044 int v4l2_compat_get_array_args(struct file *file, void *mbuf, 1045 void __user *user_ptr, size_t array_size, 1046 unsigned int cmd, void *arg) 1047 { 1048 int err = 0; 1049 1050 switch (cmd) { 1051 case VIDIOC_G_FMT32: 1052 case VIDIOC_S_FMT32: 1053 case VIDIOC_TRY_FMT32: { 1054 struct v4l2_format *f64 = arg; 1055 struct v4l2_clip *c64 = mbuf; 1056 struct v4l2_clip32 __user *c32 = user_ptr; 1057 u32 clipcount = f64->fmt.win.clipcount; 1058 1059 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1060 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1061 clipcount == 0) 1062 return 0; 1063 if (clipcount > 2048) 1064 return -EINVAL; 1065 while (clipcount--) { 1066 if (copy_from_user(c64, c32, sizeof(c64->c))) 1067 return -EFAULT; 1068 c64->next = NULL; 1069 c64++; 1070 c32++; 1071 } 1072 break; 1073 } 1074 #ifdef CONFIG_COMPAT_32BIT_TIME 1075 case VIDIOC_QUERYBUF32_TIME32: 1076 case VIDIOC_QBUF32_TIME32: 1077 case VIDIOC_DQBUF32_TIME32: 1078 case VIDIOC_PREPARE_BUF32_TIME32: 1079 #endif 1080 case VIDIOC_QUERYBUF32: 1081 case VIDIOC_QBUF32: 1082 case VIDIOC_DQBUF32: 1083 case VIDIOC_PREPARE_BUF32: { 1084 struct v4l2_buffer *b64 = arg; 1085 struct v4l2_plane *p64 = mbuf; 1086 struct v4l2_plane32 __user *p32 = user_ptr; 1087 1088 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1089 u32 num_planes = b64->length; 1090 1091 if (num_planes == 0) 1092 return 0; 1093 1094 while (num_planes--) { 1095 err = get_v4l2_plane32(p64, p32, b64->memory); 1096 if (err) 1097 return err; 1098 ++p64; 1099 ++p32; 1100 } 1101 } 1102 break; 1103 } 1104 case VIDIOC_G_EXT_CTRLS32: 1105 case VIDIOC_S_EXT_CTRLS32: 1106 case VIDIOC_TRY_EXT_CTRLS32: { 1107 struct v4l2_ext_controls *ecs64 = arg; 1108 struct v4l2_ext_control *ec64 = mbuf; 1109 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1110 int n; 1111 1112 for (n = 0; n < ecs64->count; n++) { 1113 if (copy_from_user(ec64, ec32, sizeof(*ec32))) 1114 return -EFAULT; 1115 1116 if (ctrl_is_pointer(file, ec64->id)) { 1117 compat_uptr_t p; 1118 1119 if (get_user(p, &ec32->string)) 1120 return -EFAULT; 1121 ec64->string = compat_ptr(p); 1122 } 1123 ec32++; 1124 ec64++; 1125 } 1126 break; 1127 } 1128 default: 1129 if (copy_from_user(mbuf, user_ptr, array_size)) 1130 err = -EFAULT; 1131 break; 1132 } 1133 1134 return err; 1135 } 1136 1137 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr, 1138 void *mbuf, size_t array_size, 1139 unsigned int cmd, void *arg) 1140 { 1141 int err = 0; 1142 1143 switch (cmd) { 1144 case VIDIOC_G_FMT32: 1145 case VIDIOC_S_FMT32: 1146 case VIDIOC_TRY_FMT32: { 1147 struct v4l2_format *f64 = arg; 1148 struct v4l2_clip *c64 = mbuf; 1149 struct v4l2_clip32 __user *c32 = user_ptr; 1150 u32 clipcount = f64->fmt.win.clipcount; 1151 1152 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1153 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1154 clipcount == 0) 1155 return 0; 1156 if (clipcount > 2048) 1157 return -EINVAL; 1158 while (clipcount--) { 1159 if (copy_to_user(c32, c64, sizeof(c64->c))) 1160 return -EFAULT; 1161 c64++; 1162 c32++; 1163 } 1164 break; 1165 } 1166 #ifdef CONFIG_COMPAT_32BIT_TIME 1167 case VIDIOC_QUERYBUF32_TIME32: 1168 case VIDIOC_QBUF32_TIME32: 1169 case VIDIOC_DQBUF32_TIME32: 1170 case VIDIOC_PREPARE_BUF32_TIME32: 1171 #endif 1172 case VIDIOC_QUERYBUF32: 1173 case VIDIOC_QBUF32: 1174 case VIDIOC_DQBUF32: 1175 case VIDIOC_PREPARE_BUF32: { 1176 struct v4l2_buffer *b64 = arg; 1177 struct v4l2_plane *p64 = mbuf; 1178 struct v4l2_plane32 __user *p32 = user_ptr; 1179 1180 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1181 u32 num_planes = b64->length; 1182 1183 if (num_planes == 0) 1184 return 0; 1185 1186 while (num_planes--) { 1187 err = put_v4l2_plane32(p64, p32, b64->memory); 1188 if (err) 1189 return err; 1190 ++p64; 1191 ++p32; 1192 } 1193 } 1194 break; 1195 } 1196 case VIDIOC_G_EXT_CTRLS32: 1197 case VIDIOC_S_EXT_CTRLS32: 1198 case VIDIOC_TRY_EXT_CTRLS32: { 1199 struct v4l2_ext_controls *ecs64 = arg; 1200 struct v4l2_ext_control *ec64 = mbuf; 1201 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1202 int n; 1203 1204 for (n = 0; n < ecs64->count; n++) { 1205 unsigned int size = sizeof(*ec32); 1206 /* 1207 * Do not modify the pointer when copying a pointer 1208 * control. The contents of the pointer was changed, 1209 * not the pointer itself. 1210 * The structures are otherwise compatible. 1211 */ 1212 if (ctrl_is_pointer(file, ec64->id)) 1213 size -= sizeof(ec32->value64); 1214 1215 if (copy_to_user(ec32, ec64, size)) 1216 return -EFAULT; 1217 1218 ec32++; 1219 ec64++; 1220 } 1221 break; 1222 } 1223 default: 1224 if (copy_to_user(user_ptr, mbuf, array_size)) 1225 err = -EFAULT; 1226 break; 1227 } 1228 1229 return err; 1230 } 1231 1232 /** 1233 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call 1234 * 1235 * @file: pointer to &struct file with the file handler 1236 * @cmd: ioctl to be called 1237 * @arg: arguments passed from/to the ioctl handler 1238 * 1239 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c 1240 * in order to deal with 32-bit calls on a 64-bits Kernel. 1241 * 1242 * This function calls do_video_ioctl() for non-private V4L2 ioctls. 1243 * If the function is a private one it calls vdev->fops->compat_ioctl32 1244 * instead. 1245 */ 1246 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 1247 { 1248 struct video_device *vdev = video_devdata(file); 1249 long ret = -ENOIOCTLCMD; 1250 1251 if (!file->f_op->unlocked_ioctl) 1252 return ret; 1253 1254 if (!video_is_registered(vdev)) 1255 return -ENODEV; 1256 1257 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE) 1258 ret = file->f_op->unlocked_ioctl(file, cmd, 1259 (unsigned long)compat_ptr(arg)); 1260 else if (vdev->fops->compat_ioctl32) 1261 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1262 1263 if (ret == -ENOIOCTLCMD) 1264 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1265 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); 1266 return ret; 1267 } 1268 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1269