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