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 * @reserved: future extensions 130 */ 131 struct v4l2_create_buffers32 { 132 __u32 index; 133 __u32 count; 134 __u32 memory; /* enum v4l2_memory */ 135 struct v4l2_format32 format; 136 __u32 capabilities; 137 __u32 reserved[7]; 138 }; 139 140 static int get_v4l2_format32(struct v4l2_format *p64, 141 struct v4l2_format32 __user *p32) 142 { 143 if (get_user(p64->type, &p32->type)) 144 return -EFAULT; 145 146 switch (p64->type) { 147 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 148 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 149 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix, 150 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 151 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 152 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 153 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp, 154 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 155 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 156 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 157 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 158 case V4L2_BUF_TYPE_VBI_CAPTURE: 159 case V4L2_BUF_TYPE_VBI_OUTPUT: 160 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi, 161 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 162 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 163 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 164 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced, 165 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 166 case V4L2_BUF_TYPE_SDR_CAPTURE: 167 case V4L2_BUF_TYPE_SDR_OUTPUT: 168 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr, 169 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 170 case V4L2_BUF_TYPE_META_CAPTURE: 171 case V4L2_BUF_TYPE_META_OUTPUT: 172 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta, 173 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 174 default: 175 return -EINVAL; 176 } 177 } 178 179 static int get_v4l2_create32(struct v4l2_create_buffers *p64, 180 struct v4l2_create_buffers32 __user *p32) 181 { 182 if (copy_from_user(p64, p32, 183 offsetof(struct v4l2_create_buffers32, format))) 184 return -EFAULT; 185 return get_v4l2_format32(&p64->format, &p32->format); 186 } 187 188 static int put_v4l2_format32(struct v4l2_format *p64, 189 struct v4l2_format32 __user *p32) 190 { 191 switch (p64->type) { 192 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 193 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 194 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix, 195 sizeof(p64->fmt.pix)) ? -EFAULT : 0; 196 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 197 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 198 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp, 199 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0; 200 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 201 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 202 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win); 203 case V4L2_BUF_TYPE_VBI_CAPTURE: 204 case V4L2_BUF_TYPE_VBI_OUTPUT: 205 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi, 206 sizeof(p64->fmt.vbi)) ? -EFAULT : 0; 207 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 208 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 209 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced, 210 sizeof(p64->fmt.sliced)) ? -EFAULT : 0; 211 case V4L2_BUF_TYPE_SDR_CAPTURE: 212 case V4L2_BUF_TYPE_SDR_OUTPUT: 213 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr, 214 sizeof(p64->fmt.sdr)) ? -EFAULT : 0; 215 case V4L2_BUF_TYPE_META_CAPTURE: 216 case V4L2_BUF_TYPE_META_OUTPUT: 217 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta, 218 sizeof(p64->fmt.meta)) ? -EFAULT : 0; 219 default: 220 return -EINVAL; 221 } 222 } 223 224 static int put_v4l2_create32(struct v4l2_create_buffers *p64, 225 struct v4l2_create_buffers32 __user *p32) 226 { 227 if (copy_to_user(p32, p64, 228 offsetof(struct v4l2_create_buffers32, format)) || 229 put_user(p64->capabilities, &p32->capabilities) || 230 copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved))) 231 return -EFAULT; 232 return put_v4l2_format32(&p64->format, &p32->format); 233 } 234 235 struct v4l2_standard32 { 236 __u32 index; 237 compat_u64 id; 238 __u8 name[24]; 239 struct v4l2_fract frameperiod; /* Frames, not fields */ 240 __u32 framelines; 241 __u32 reserved[4]; 242 }; 243 244 static int get_v4l2_standard32(struct v4l2_standard *p64, 245 struct v4l2_standard32 __user *p32) 246 { 247 /* other fields are not set by the user, nor used by the driver */ 248 return get_user(p64->index, &p32->index); 249 } 250 251 static int put_v4l2_standard32(struct v4l2_standard *p64, 252 struct v4l2_standard32 __user *p32) 253 { 254 if (put_user(p64->index, &p32->index) || 255 put_user(p64->id, &p32->id) || 256 copy_to_user(p32->name, p64->name, sizeof(p32->name)) || 257 copy_to_user(&p32->frameperiod, &p64->frameperiod, 258 sizeof(p32->frameperiod)) || 259 put_user(p64->framelines, &p32->framelines) || 260 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 261 return -EFAULT; 262 return 0; 263 } 264 265 struct v4l2_plane32 { 266 __u32 bytesused; 267 __u32 length; 268 union { 269 __u32 mem_offset; 270 compat_long_t userptr; 271 __s32 fd; 272 } m; 273 __u32 data_offset; 274 __u32 reserved[11]; 275 }; 276 277 /* 278 * This is correct for all architectures including i386, but not x32, 279 * which has different alignment requirements for timestamp 280 */ 281 struct v4l2_buffer32 { 282 __u32 index; 283 __u32 type; /* enum v4l2_buf_type */ 284 __u32 bytesused; 285 __u32 flags; 286 __u32 field; /* enum v4l2_field */ 287 struct { 288 compat_s64 tv_sec; 289 compat_s64 tv_usec; 290 } timestamp; 291 struct v4l2_timecode timecode; 292 __u32 sequence; 293 294 /* memory location */ 295 __u32 memory; /* enum v4l2_memory */ 296 union { 297 __u32 offset; 298 compat_long_t userptr; 299 compat_caddr_t planes; 300 __s32 fd; 301 } m; 302 __u32 length; 303 __u32 reserved2; 304 __s32 request_fd; 305 }; 306 307 #ifdef CONFIG_COMPAT_32BIT_TIME 308 struct v4l2_buffer32_time32 { 309 __u32 index; 310 __u32 type; /* enum v4l2_buf_type */ 311 __u32 bytesused; 312 __u32 flags; 313 __u32 field; /* enum v4l2_field */ 314 struct old_timeval32 timestamp; 315 struct v4l2_timecode timecode; 316 __u32 sequence; 317 318 /* memory location */ 319 __u32 memory; /* enum v4l2_memory */ 320 union { 321 __u32 offset; 322 compat_long_t userptr; 323 compat_caddr_t planes; 324 __s32 fd; 325 } m; 326 __u32 length; 327 __u32 reserved2; 328 __s32 request_fd; 329 }; 330 #endif 331 332 static int get_v4l2_plane32(struct v4l2_plane *p64, 333 struct v4l2_plane32 __user *p32, 334 enum v4l2_memory memory) 335 { 336 struct v4l2_plane32 plane32; 337 typeof(p64->m) m = {}; 338 339 if (copy_from_user(&plane32, p32, sizeof(plane32))) 340 return -EFAULT; 341 342 switch (memory) { 343 case V4L2_MEMORY_MMAP: 344 case V4L2_MEMORY_OVERLAY: 345 m.mem_offset = plane32.m.mem_offset; 346 break; 347 case V4L2_MEMORY_USERPTR: 348 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr); 349 break; 350 case V4L2_MEMORY_DMABUF: 351 m.fd = plane32.m.fd; 352 break; 353 } 354 355 memset(p64, 0, sizeof(*p64)); 356 *p64 = (struct v4l2_plane) { 357 .bytesused = plane32.bytesused, 358 .length = plane32.length, 359 .m = m, 360 .data_offset = plane32.data_offset, 361 }; 362 363 return 0; 364 } 365 366 static int put_v4l2_plane32(struct v4l2_plane *p64, 367 struct v4l2_plane32 __user *p32, 368 enum v4l2_memory memory) 369 { 370 struct v4l2_plane32 plane32; 371 372 memset(&plane32, 0, sizeof(plane32)); 373 plane32 = (struct v4l2_plane32) { 374 .bytesused = p64->bytesused, 375 .length = p64->length, 376 .data_offset = p64->data_offset, 377 }; 378 379 switch (memory) { 380 case V4L2_MEMORY_MMAP: 381 case V4L2_MEMORY_OVERLAY: 382 plane32.m.mem_offset = p64->m.mem_offset; 383 break; 384 case V4L2_MEMORY_USERPTR: 385 plane32.m.userptr = (uintptr_t)(p64->m.userptr); 386 break; 387 case V4L2_MEMORY_DMABUF: 388 plane32.m.fd = p64->m.fd; 389 break; 390 } 391 392 if (copy_to_user(p32, &plane32, sizeof(plane32))) 393 return -EFAULT; 394 395 return 0; 396 } 397 398 static int get_v4l2_buffer32(struct v4l2_buffer *vb, 399 struct v4l2_buffer32 __user *arg) 400 { 401 struct v4l2_buffer32 vb32; 402 403 if (copy_from_user(&vb32, arg, sizeof(vb32))) 404 return -EFAULT; 405 406 memset(vb, 0, sizeof(*vb)); 407 *vb = (struct v4l2_buffer) { 408 .index = vb32.index, 409 .type = vb32.type, 410 .bytesused = vb32.bytesused, 411 .flags = vb32.flags, 412 .field = vb32.field, 413 .timestamp.tv_sec = vb32.timestamp.tv_sec, 414 .timestamp.tv_usec = vb32.timestamp.tv_usec, 415 .timecode = vb32.timecode, 416 .sequence = vb32.sequence, 417 .memory = vb32.memory, 418 .m.offset = vb32.m.offset, 419 .length = vb32.length, 420 .request_fd = vb32.request_fd, 421 }; 422 423 switch (vb->memory) { 424 case V4L2_MEMORY_MMAP: 425 case V4L2_MEMORY_OVERLAY: 426 vb->m.offset = vb32.m.offset; 427 break; 428 case V4L2_MEMORY_USERPTR: 429 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 430 break; 431 case V4L2_MEMORY_DMABUF: 432 vb->m.fd = vb32.m.fd; 433 break; 434 } 435 436 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 437 vb->m.planes = (void __force *) 438 compat_ptr(vb32.m.planes); 439 440 return 0; 441 } 442 443 #ifdef CONFIG_COMPAT_32BIT_TIME 444 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb, 445 struct v4l2_buffer32_time32 __user *arg) 446 { 447 struct v4l2_buffer32_time32 vb32; 448 449 if (copy_from_user(&vb32, arg, sizeof(vb32))) 450 return -EFAULT; 451 452 *vb = (struct v4l2_buffer) { 453 .index = vb32.index, 454 .type = vb32.type, 455 .bytesused = vb32.bytesused, 456 .flags = vb32.flags, 457 .field = vb32.field, 458 .timestamp.tv_sec = vb32.timestamp.tv_sec, 459 .timestamp.tv_usec = vb32.timestamp.tv_usec, 460 .timecode = vb32.timecode, 461 .sequence = vb32.sequence, 462 .memory = vb32.memory, 463 .m.offset = vb32.m.offset, 464 .length = vb32.length, 465 .request_fd = vb32.request_fd, 466 }; 467 switch (vb->memory) { 468 case V4L2_MEMORY_MMAP: 469 case V4L2_MEMORY_OVERLAY: 470 vb->m.offset = vb32.m.offset; 471 break; 472 case V4L2_MEMORY_USERPTR: 473 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr); 474 break; 475 case V4L2_MEMORY_DMABUF: 476 vb->m.fd = vb32.m.fd; 477 break; 478 } 479 480 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 481 vb->m.planes = (void __force *) 482 compat_ptr(vb32.m.planes); 483 484 return 0; 485 } 486 #endif 487 488 static int put_v4l2_buffer32(struct v4l2_buffer *vb, 489 struct v4l2_buffer32 __user *arg) 490 { 491 struct v4l2_buffer32 vb32; 492 493 memset(&vb32, 0, sizeof(vb32)); 494 vb32 = (struct v4l2_buffer32) { 495 .index = vb->index, 496 .type = vb->type, 497 .bytesused = vb->bytesused, 498 .flags = vb->flags, 499 .field = vb->field, 500 .timestamp.tv_sec = vb->timestamp.tv_sec, 501 .timestamp.tv_usec = vb->timestamp.tv_usec, 502 .timecode = vb->timecode, 503 .sequence = vb->sequence, 504 .memory = vb->memory, 505 .m.offset = vb->m.offset, 506 .length = vb->length, 507 .request_fd = vb->request_fd, 508 }; 509 510 switch (vb->memory) { 511 case V4L2_MEMORY_MMAP: 512 case V4L2_MEMORY_OVERLAY: 513 vb32.m.offset = vb->m.offset; 514 break; 515 case V4L2_MEMORY_USERPTR: 516 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 517 break; 518 case V4L2_MEMORY_DMABUF: 519 vb32.m.fd = vb->m.fd; 520 break; 521 } 522 523 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 524 vb32.m.planes = (uintptr_t)vb->m.planes; 525 526 if (copy_to_user(arg, &vb32, sizeof(vb32))) 527 return -EFAULT; 528 529 return 0; 530 } 531 532 #ifdef CONFIG_COMPAT_32BIT_TIME 533 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb, 534 struct v4l2_buffer32_time32 __user *arg) 535 { 536 struct v4l2_buffer32_time32 vb32; 537 538 memset(&vb32, 0, sizeof(vb32)); 539 vb32 = (struct v4l2_buffer32_time32) { 540 .index = vb->index, 541 .type = vb->type, 542 .bytesused = vb->bytesused, 543 .flags = vb->flags, 544 .field = vb->field, 545 .timestamp.tv_sec = vb->timestamp.tv_sec, 546 .timestamp.tv_usec = vb->timestamp.tv_usec, 547 .timecode = vb->timecode, 548 .sequence = vb->sequence, 549 .memory = vb->memory, 550 .m.offset = vb->m.offset, 551 .length = vb->length, 552 .request_fd = vb->request_fd, 553 }; 554 switch (vb->memory) { 555 case V4L2_MEMORY_MMAP: 556 case V4L2_MEMORY_OVERLAY: 557 vb32.m.offset = vb->m.offset; 558 break; 559 case V4L2_MEMORY_USERPTR: 560 vb32.m.userptr = (uintptr_t)(vb->m.userptr); 561 break; 562 case V4L2_MEMORY_DMABUF: 563 vb32.m.fd = vb->m.fd; 564 break; 565 } 566 567 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type)) 568 vb32.m.planes = (uintptr_t)vb->m.planes; 569 570 if (copy_to_user(arg, &vb32, sizeof(vb32))) 571 return -EFAULT; 572 573 return 0; 574 } 575 #endif 576 577 struct v4l2_framebuffer32 { 578 __u32 capability; 579 __u32 flags; 580 compat_caddr_t base; 581 struct { 582 __u32 width; 583 __u32 height; 584 __u32 pixelformat; 585 __u32 field; 586 __u32 bytesperline; 587 __u32 sizeimage; 588 __u32 colorspace; 589 __u32 priv; 590 } fmt; 591 }; 592 593 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 594 struct v4l2_framebuffer32 __user *p32) 595 { 596 compat_caddr_t tmp; 597 598 if (get_user(tmp, &p32->base) || 599 get_user(p64->capability, &p32->capability) || 600 get_user(p64->flags, &p32->flags) || 601 copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt))) 602 return -EFAULT; 603 p64->base = (void __force *)compat_ptr(tmp); 604 605 return 0; 606 } 607 608 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64, 609 struct v4l2_framebuffer32 __user *p32) 610 { 611 if (put_user((uintptr_t)p64->base, &p32->base) || 612 put_user(p64->capability, &p32->capability) || 613 put_user(p64->flags, &p32->flags) || 614 copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt))) 615 return -EFAULT; 616 617 return 0; 618 } 619 620 struct v4l2_input32 { 621 __u32 index; /* Which input */ 622 __u8 name[32]; /* Label */ 623 __u32 type; /* Type of input */ 624 __u32 audioset; /* Associated audios (bitfield) */ 625 __u32 tuner; /* Associated tuner */ 626 compat_u64 std; 627 __u32 status; 628 __u32 capabilities; 629 __u32 reserved[3]; 630 }; 631 632 /* 633 * The 64-bit v4l2_input struct has extra padding at the end of the struct. 634 * Otherwise it is identical to the 32-bit version. 635 */ 636 static inline int get_v4l2_input32(struct v4l2_input *p64, 637 struct v4l2_input32 __user *p32) 638 { 639 if (copy_from_user(p64, p32, sizeof(*p32))) 640 return -EFAULT; 641 return 0; 642 } 643 644 static inline int put_v4l2_input32(struct v4l2_input *p64, 645 struct v4l2_input32 __user *p32) 646 { 647 if (copy_to_user(p32, p64, sizeof(*p32))) 648 return -EFAULT; 649 return 0; 650 } 651 652 struct v4l2_ext_controls32 { 653 __u32 which; 654 __u32 count; 655 __u32 error_idx; 656 __s32 request_fd; 657 __u32 reserved[1]; 658 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ 659 }; 660 661 struct v4l2_ext_control32 { 662 __u32 id; 663 __u32 size; 664 __u32 reserved2[1]; 665 union { 666 __s32 value; 667 __s64 value64; 668 compat_caddr_t string; /* actually char * */ 669 }; 670 } __attribute__ ((packed)); 671 672 /* Return true if this control is a pointer type. */ 673 static inline bool ctrl_is_pointer(struct file *file, u32 id) 674 { 675 struct video_device *vdev = video_devdata(file); 676 struct v4l2_fh *fh = NULL; 677 struct v4l2_ctrl_handler *hdl = NULL; 678 struct v4l2_query_ext_ctrl qec = { id }; 679 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; 680 681 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) 682 fh = file->private_data; 683 684 if (fh && fh->ctrl_handler) 685 hdl = fh->ctrl_handler; 686 else if (vdev->ctrl_handler) 687 hdl = vdev->ctrl_handler; 688 689 if (hdl) { 690 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); 691 692 return ctrl && ctrl->is_ptr; 693 } 694 695 if (!ops || !ops->vidioc_query_ext_ctrl) 696 return false; 697 698 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && 699 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); 700 } 701 702 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 703 struct v4l2_ext_controls32 __user *p32) 704 { 705 struct v4l2_ext_controls32 ec32; 706 707 if (copy_from_user(&ec32, p32, sizeof(ec32))) 708 return -EFAULT; 709 710 *p64 = (struct v4l2_ext_controls) { 711 .which = ec32.which, 712 .count = ec32.count, 713 .error_idx = ec32.error_idx, 714 .request_fd = ec32.request_fd, 715 .reserved[0] = ec32.reserved[0], 716 .controls = (void __force *)compat_ptr(ec32.controls), 717 }; 718 719 return 0; 720 } 721 722 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, 723 struct v4l2_ext_controls32 __user *p32) 724 { 725 struct v4l2_ext_controls32 ec32; 726 727 memset(&ec32, 0, sizeof(ec32)); 728 ec32 = (struct v4l2_ext_controls32) { 729 .which = p64->which, 730 .count = p64->count, 731 .error_idx = p64->error_idx, 732 .request_fd = p64->request_fd, 733 .reserved[0] = p64->reserved[0], 734 .controls = (uintptr_t)p64->controls, 735 }; 736 737 if (copy_to_user(p32, &ec32, sizeof(ec32))) 738 return -EFAULT; 739 740 return 0; 741 } 742 743 #ifdef CONFIG_X86_64 744 /* 745 * x86 is the only compat architecture with different struct alignment 746 * between 32-bit and 64-bit tasks. 747 * 748 * On all other architectures, v4l2_event32 and v4l2_event32_time32 are 749 * the same as v4l2_event and v4l2_event_time32, so we can use the native 750 * handlers, converting v4l2_event to v4l2_event_time32 if necessary. 751 */ 752 struct v4l2_event32 { 753 __u32 type; 754 union { 755 compat_s64 value64; 756 __u8 data[64]; 757 } u; 758 __u32 pending; 759 __u32 sequence; 760 struct { 761 compat_s64 tv_sec; 762 compat_s64 tv_nsec; 763 } timestamp; 764 __u32 id; 765 __u32 reserved[8]; 766 }; 767 768 #ifdef CONFIG_COMPAT_32BIT_TIME 769 struct v4l2_event32_time32 { 770 __u32 type; 771 union { 772 compat_s64 value64; 773 __u8 data[64]; 774 } u; 775 __u32 pending; 776 __u32 sequence; 777 struct old_timespec32 timestamp; 778 __u32 id; 779 __u32 reserved[8]; 780 }; 781 #endif 782 783 static int put_v4l2_event32(struct v4l2_event *p64, 784 struct v4l2_event32 __user *p32) 785 { 786 if (put_user(p64->type, &p32->type) || 787 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 788 put_user(p64->pending, &p32->pending) || 789 put_user(p64->sequence, &p32->sequence) || 790 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 791 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 792 put_user(p64->id, &p32->id) || 793 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 794 return -EFAULT; 795 return 0; 796 } 797 798 #ifdef CONFIG_COMPAT_32BIT_TIME 799 static int put_v4l2_event32_time32(struct v4l2_event *p64, 800 struct v4l2_event32_time32 __user *p32) 801 { 802 if (put_user(p64->type, &p32->type) || 803 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) || 804 put_user(p64->pending, &p32->pending) || 805 put_user(p64->sequence, &p32->sequence) || 806 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) || 807 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) || 808 put_user(p64->id, &p32->id) || 809 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved))) 810 return -EFAULT; 811 return 0; 812 } 813 #endif 814 #endif 815 816 struct v4l2_edid32 { 817 __u32 pad; 818 __u32 start_block; 819 __u32 blocks; 820 __u32 reserved[5]; 821 compat_caddr_t edid; 822 }; 823 824 static int get_v4l2_edid32(struct v4l2_edid *p64, 825 struct v4l2_edid32 __user *p32) 826 { 827 compat_uptr_t edid; 828 829 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) || 830 get_user(edid, &p32->edid)) 831 return -EFAULT; 832 833 p64->edid = (void __force *)compat_ptr(edid); 834 return 0; 835 } 836 837 static int put_v4l2_edid32(struct v4l2_edid *p64, 838 struct v4l2_edid32 __user *p32) 839 { 840 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid))) 841 return -EFAULT; 842 return 0; 843 } 844 845 /* 846 * List of ioctls that require 32-bits/64-bits conversion 847 * 848 * The V4L2 ioctls that aren't listed there don't have pointer arguments 849 * and the struct size is identical for both 32 and 64 bits versions, so 850 * they don't need translations. 851 */ 852 853 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32) 854 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32) 855 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32) 856 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 857 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 858 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32) 859 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) 860 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) 861 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) 862 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32) 863 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32) 864 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) 865 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) 866 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) 867 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32) 868 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32) 869 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32) 870 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32) 871 872 #ifdef CONFIG_COMPAT_32BIT_TIME 873 #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) 874 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) 875 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) 876 #ifdef CONFIG_X86_64 877 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) 878 #endif 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 #ifdef CONFIG_COMPAT_32BIT_TIME 933 case VIDIOC_DQEVENT32_TIME32: 934 return VIDIOC_DQEVENT; 935 #endif 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 #ifdef CONFIG_COMPAT_32BIT_TIME 1029 case VIDIOC_DQEVENT32_TIME32: 1030 return put_v4l2_event32_time32(parg, arg); 1031 #endif 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 switch (cmd) { 1044 case VIDIOC_G_FMT32: 1045 case VIDIOC_S_FMT32: 1046 case VIDIOC_TRY_FMT32: { 1047 struct v4l2_format *f64 = arg; 1048 struct v4l2_clip *c64 = mbuf; 1049 struct v4l2_clip32 __user *c32 = user_ptr; 1050 u32 clipcount = f64->fmt.win.clipcount; 1051 1052 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1053 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1054 clipcount == 0) 1055 return 0; 1056 if (clipcount > 2048) 1057 return -EINVAL; 1058 while (clipcount--) { 1059 if (copy_from_user(c64, c32, sizeof(c64->c))) 1060 return -EFAULT; 1061 c64->next = NULL; 1062 c64++; 1063 c32++; 1064 } 1065 break; 1066 } 1067 #ifdef CONFIG_COMPAT_32BIT_TIME 1068 case VIDIOC_QUERYBUF32_TIME32: 1069 case VIDIOC_QBUF32_TIME32: 1070 case VIDIOC_DQBUF32_TIME32: 1071 case VIDIOC_PREPARE_BUF32_TIME32: 1072 #endif 1073 case VIDIOC_QUERYBUF32: 1074 case VIDIOC_QBUF32: 1075 case VIDIOC_DQBUF32: 1076 case VIDIOC_PREPARE_BUF32: { 1077 struct v4l2_buffer *b64 = arg; 1078 struct v4l2_plane *p64 = mbuf; 1079 struct v4l2_plane32 __user *p32 = user_ptr; 1080 1081 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1082 u32 num_planes = b64->length; 1083 1084 if (num_planes == 0) 1085 return 0; 1086 1087 while (num_planes--) { 1088 err = get_v4l2_plane32(p64, p32, b64->memory); 1089 if (err) 1090 return err; 1091 ++p64; 1092 ++p32; 1093 } 1094 } 1095 break; 1096 } 1097 case VIDIOC_G_EXT_CTRLS32: 1098 case VIDIOC_S_EXT_CTRLS32: 1099 case VIDIOC_TRY_EXT_CTRLS32: { 1100 struct v4l2_ext_controls *ecs64 = arg; 1101 struct v4l2_ext_control *ec64 = mbuf; 1102 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1103 int n; 1104 1105 for (n = 0; n < ecs64->count; n++) { 1106 if (copy_from_user(ec64, ec32, sizeof(*ec32))) 1107 return -EFAULT; 1108 1109 if (ctrl_is_pointer(file, ec64->id)) { 1110 compat_uptr_t p; 1111 1112 if (get_user(p, &ec32->string)) 1113 return -EFAULT; 1114 ec64->string = compat_ptr(p); 1115 } 1116 ec32++; 1117 ec64++; 1118 } 1119 break; 1120 } 1121 default: 1122 if (copy_from_user(mbuf, user_ptr, array_size)) 1123 err = -EFAULT; 1124 break; 1125 } 1126 1127 return err; 1128 } 1129 1130 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr, 1131 void *mbuf, size_t array_size, 1132 unsigned int cmd, void *arg) 1133 { 1134 int err = 0; 1135 1136 switch (cmd) { 1137 case VIDIOC_G_FMT32: 1138 case VIDIOC_S_FMT32: 1139 case VIDIOC_TRY_FMT32: { 1140 struct v4l2_format *f64 = arg; 1141 struct v4l2_clip *c64 = mbuf; 1142 struct v4l2_clip32 __user *c32 = user_ptr; 1143 u32 clipcount = f64->fmt.win.clipcount; 1144 1145 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY && 1146 f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) || 1147 clipcount == 0) 1148 return 0; 1149 if (clipcount > 2048) 1150 return -EINVAL; 1151 while (clipcount--) { 1152 if (copy_to_user(c32, c64, sizeof(c64->c))) 1153 return -EFAULT; 1154 c64++; 1155 c32++; 1156 } 1157 break; 1158 } 1159 #ifdef CONFIG_COMPAT_32BIT_TIME 1160 case VIDIOC_QUERYBUF32_TIME32: 1161 case VIDIOC_QBUF32_TIME32: 1162 case VIDIOC_DQBUF32_TIME32: 1163 case VIDIOC_PREPARE_BUF32_TIME32: 1164 #endif 1165 case VIDIOC_QUERYBUF32: 1166 case VIDIOC_QBUF32: 1167 case VIDIOC_DQBUF32: 1168 case VIDIOC_PREPARE_BUF32: { 1169 struct v4l2_buffer *b64 = arg; 1170 struct v4l2_plane *p64 = mbuf; 1171 struct v4l2_plane32 __user *p32 = user_ptr; 1172 1173 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) { 1174 u32 num_planes = b64->length; 1175 1176 if (num_planes == 0) 1177 return 0; 1178 1179 while (num_planes--) { 1180 err = put_v4l2_plane32(p64, p32, b64->memory); 1181 if (err) 1182 return err; 1183 ++p64; 1184 ++p32; 1185 } 1186 } 1187 break; 1188 } 1189 case VIDIOC_G_EXT_CTRLS32: 1190 case VIDIOC_S_EXT_CTRLS32: 1191 case VIDIOC_TRY_EXT_CTRLS32: { 1192 struct v4l2_ext_controls *ecs64 = arg; 1193 struct v4l2_ext_control *ec64 = mbuf; 1194 struct v4l2_ext_control32 __user *ec32 = user_ptr; 1195 int n; 1196 1197 for (n = 0; n < ecs64->count; n++) { 1198 unsigned int size = sizeof(*ec32); 1199 /* 1200 * Do not modify the pointer when copying a pointer 1201 * control. The contents of the pointer was changed, 1202 * not the pointer itself. 1203 * The structures are otherwise compatible. 1204 */ 1205 if (ctrl_is_pointer(file, ec64->id)) 1206 size -= sizeof(ec32->value64); 1207 1208 if (copy_to_user(ec32, ec64, size)) 1209 return -EFAULT; 1210 1211 ec32++; 1212 ec64++; 1213 } 1214 break; 1215 } 1216 default: 1217 if (copy_to_user(user_ptr, mbuf, array_size)) 1218 err = -EFAULT; 1219 break; 1220 } 1221 1222 return err; 1223 } 1224 1225 /** 1226 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call 1227 * 1228 * @file: pointer to &struct file with the file handler 1229 * @cmd: ioctl to be called 1230 * @arg: arguments passed from/to the ioctl handler 1231 * 1232 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c 1233 * in order to deal with 32-bit calls on a 64-bits Kernel. 1234 * 1235 * This function calls do_video_ioctl() for non-private V4L2 ioctls. 1236 * If the function is a private one it calls vdev->fops->compat_ioctl32 1237 * instead. 1238 */ 1239 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 1240 { 1241 struct video_device *vdev = video_devdata(file); 1242 long ret = -ENOIOCTLCMD; 1243 1244 if (!file->f_op->unlocked_ioctl) 1245 return ret; 1246 1247 if (!video_is_registered(vdev)) 1248 return -ENODEV; 1249 1250 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE) 1251 ret = file->f_op->unlocked_ioctl(file, cmd, 1252 (unsigned long)compat_ptr(arg)); 1253 else if (vdev->fops->compat_ioctl32) 1254 ret = vdev->fops->compat_ioctl32(file, cmd, arg); 1255 1256 if (ret == -ENOIOCTLCMD) 1257 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", 1258 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); 1259 return ret; 1260 } 1261 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); 1262