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