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 struct v4l2_event32 { 756 __u32 type; 757 union { 758 compat_s64 value64; 759 __u8 data[64]; 760 } u; 761 __u32 pending; 762 __u32 sequence; 763 struct { 764 compat_s64 tv_sec; 765 compat_s64 tv_nsec; 766 } timestamp; 767 __u32 id; 768 __u32 reserved[8]; 769 }; 770 771 static int put_v4l2_event32(struct v4l2_event *p64, 772 struct v4l2_event32 __user *p32) 773 { 774 if (put_user(p64->type, &p32->type) || 775 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 776 put_user(p64->pending, &p32->pending) || 777 put_user(p64->sequence, &p32->sequence) || 778 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 779 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 780 put_user(p64->id, &p32->id) || 781 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 782 return -EFAULT; 783 return 0; 784 } 785 786 #endif 787 788 #ifdef CONFIG_COMPAT_32BIT_TIME 789 struct v4l2_event32_time32 { 790 __u32 type; 791 union { 792 compat_s64 value64; 793 __u8 data[64]; 794 } u; 795 __u32 pending; 796 __u32 sequence; 797 struct old_timespec32 timestamp; 798 __u32 id; 799 __u32 reserved[8]; 800 }; 801 802 static int put_v4l2_event32_time32(struct v4l2_event *p64, 803 struct v4l2_event32_time32 __user *p32) 804 { 805 if (put_user(p64->type, &p32->type) || 806 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 807 put_user(p64->pending, &p32->pending) || 808 put_user(p64->sequence, &p32->sequence) || 809 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 810 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 811 put_user(p64->id, &p32->id) || 812 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 813 return -EFAULT; 814 return 0; 815 } 816 #endif 817 818 struct v4l2_edid32 { 819 __u32 pad; 820 __u32 start_block; 821 __u32 blocks; 822 __u32 reserved[5]; 823 compat_caddr_t edid; 824 }; 825 826 static int get_v4l2_edid32(struct v4l2_edid *p64, 827 struct v4l2_edid32 __user *p32) 828 { 829 compat_uptr_t edid; 830 831 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) || 832 get_user(edid, &p32->edid)) 833 return -EFAULT; 834 835 p64->edid = (void __force *)compat_ptr(edid); 836 return 0; 837 } 838 839 static int put_v4l2_edid32(struct v4l2_edid *p64, 840 struct v4l2_edid32 __user *p32) 841 { 842 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid))) 843 return -EFAULT; 844 return 0; 845 } 846 847 /* 848 * List of ioctls that require 32-bits/64-bits conversion 849 * 850 * The V4L2 ioctls that aren't listed there don't have pointer arguments 851 * and the struct size is identical for both 32 and 64 bits versions, so 852 * they don't need translations. 853 */ 854 855 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 856 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 857 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 858 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 859 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 860 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 861 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 862 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 863 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 864 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) 865 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) 866 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 867 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 868 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 869 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 870 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 871 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 872 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 873 874 #ifdef CONFIG_COMPAT_32BIT_TIME 875 #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) 876 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) 877 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) 878 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) 879 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) 880 #endif 881 882 unsigned int v4l2_compat_translate_cmd(unsigned int cmd) 883 { 884 switch (cmd) { 885 case VIDIOC_G_FMT32: 886 return VIDIOC_G_FMT; 887 case VIDIOC_S_FMT32: 888 return VIDIOC_S_FMT; 889 case VIDIOC_TRY_FMT32: 890 return VIDIOC_TRY_FMT; 891 case VIDIOC_G_FBUF32: 892 return VIDIOC_G_FBUF; 893 case VIDIOC_S_FBUF32: 894 return VIDIOC_S_FBUF; 895 #ifdef CONFIG_COMPAT_32BIT_TIME 896 case VIDIOC_QUERYBUF32_TIME32: 897 return VIDIOC_QUERYBUF; 898 case VIDIOC_QBUF32_TIME32: 899 return VIDIOC_QBUF; 900 case VIDIOC_DQBUF32_TIME32: 901 return VIDIOC_DQBUF; 902 case VIDIOC_PREPARE_BUF32_TIME32: 903 return VIDIOC_PREPARE_BUF; 904 #endif 905 case VIDIOC_QUERYBUF32: 906 return VIDIOC_QUERYBUF; 907 case VIDIOC_QBUF32: 908 return VIDIOC_QBUF; 909 case VIDIOC_DQBUF32: 910 return VIDIOC_DQBUF; 911 case VIDIOC_CREATE_BUFS32: 912 return VIDIOC_CREATE_BUFS; 913 case VIDIOC_G_EXT_CTRLS32: 914 return VIDIOC_G_EXT_CTRLS; 915 case VIDIOC_S_EXT_CTRLS32: 916 return VIDIOC_S_EXT_CTRLS; 917 case VIDIOC_TRY_EXT_CTRLS32: 918 return VIDIOC_TRY_EXT_CTRLS; 919 case VIDIOC_PREPARE_BUF32: 920 return VIDIOC_PREPARE_BUF; 921 case VIDIOC_ENUMSTD32: 922 return VIDIOC_ENUMSTD; 923 case VIDIOC_ENUMINPUT32: 924 return VIDIOC_ENUMINPUT; 925 case VIDIOC_G_EDID32: 926 return VIDIOC_G_EDID; 927 case VIDIOC_S_EDID32: 928 return VIDIOC_S_EDID; 929 #ifdef CONFIG_X86_64 930 case VIDIOC_DQEVENT32: 931 return VIDIOC_DQEVENT; 932 #endif 933 #ifdef CONFIG_COMPAT_32BIT_TIME 934 case VIDIOC_DQEVENT32_TIME32: 935 return VIDIOC_DQEVENT; 936 #endif 937 } 938 return cmd; 939 } 940 941 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd) 942 { 943 switch (cmd) { 944 case VIDIOC_G_FMT32: 945 case VIDIOC_S_FMT32: 946 case VIDIOC_TRY_FMT32: 947 return get_v4l2_format32(parg, arg); 948 949 case VIDIOC_S_FBUF32: 950 return get_v4l2_framebuffer32(parg, arg); 951 #ifdef CONFIG_COMPAT_32BIT_TIME 952 case VIDIOC_QUERYBUF32_TIME32: 953 case VIDIOC_QBUF32_TIME32: 954 case VIDIOC_DQBUF32_TIME32: 955 case VIDIOC_PREPARE_BUF32_TIME32: 956 return get_v4l2_buffer32_time32(parg, arg); 957 #endif 958 case VIDIOC_QUERYBUF32: 959 case VIDIOC_QBUF32: 960 case VIDIOC_DQBUF32: 961 case VIDIOC_PREPARE_BUF32: 962 return get_v4l2_buffer32(parg, arg); 963 964 case VIDIOC_G_EXT_CTRLS32: 965 case VIDIOC_S_EXT_CTRLS32: 966 case VIDIOC_TRY_EXT_CTRLS32: 967 return get_v4l2_ext_controls32(parg, arg); 968 969 case VIDIOC_CREATE_BUFS32: 970 return get_v4l2_create32(parg, arg); 971 972 case VIDIOC_ENUMSTD32: 973 return get_v4l2_standard32(parg, arg); 974 975 case VIDIOC_ENUMINPUT32: 976 return get_v4l2_input32(parg, arg); 977 978 case VIDIOC_G_EDID32: 979 case VIDIOC_S_EDID32: 980 return get_v4l2_edid32(parg, arg); 981 } 982 return 0; 983 } 984 985 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) 986 { 987 switch (cmd) { 988 case VIDIOC_G_FMT32: 989 case VIDIOC_S_FMT32: 990 case VIDIOC_TRY_FMT32: 991 return put_v4l2_format32(parg, arg); 992 993 case VIDIOC_G_FBUF32: 994 return put_v4l2_framebuffer32(parg, arg); 995 #ifdef CONFIG_COMPAT_32BIT_TIME 996 case VIDIOC_QUERYBUF32_TIME32: 997 case VIDIOC_QBUF32_TIME32: 998 case VIDIOC_DQBUF32_TIME32: 999 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 * Do not modify the pointer when copying a pointer 1203 * control. The contents of the pointer was changed, 1204 * not the pointer itself. 1205 * The structures are otherwise compatible. 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 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call 1229 * 1230 * @file: pointer to &struct file with the file handler 1231 * @cmd: ioctl to be called 1232 * @arg: arguments passed from/to the ioctl handler 1233 * 1234 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c 1235 * in order to deal with 32-bit calls on a 64-bits Kernel. 1236 * 1237 * This function calls do_video_ioctl() for non-private V4L2 ioctls. 1238 * If the function is a private one it calls vdev->fops->compat_ioctl32 1239 * instead. 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); 1264