Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.21 926 lines 25 kB view raw
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@suse.cz) 9 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be) 10 * 11 * These routines maintain argument size conversion between 32bit and 64bit 12 * ioctls. 13 */ 14 15#include <linux/compat.h> 16#include <linux/videodev.h> 17#include <linux/videodev2.h> 18#include <linux/module.h> 19#include <linux/smp_lock.h> 20#include <media/v4l2-common.h> 21 22#ifdef CONFIG_COMPAT 23 24#ifdef CONFIG_VIDEO_V4L1_COMPAT 25struct video_tuner32 { 26 compat_int_t tuner; 27 char name[32]; 28 compat_ulong_t rangelow, rangehigh; 29 u32 flags; /* It is really u32 in videodev.h */ 30 u16 mode, signal; 31}; 32 33static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 34{ 35 if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || 36 get_user(kp->tuner, &up->tuner) || 37 copy_from_user(kp->name, up->name, 32) || 38 get_user(kp->rangelow, &up->rangelow) || 39 get_user(kp->rangehigh, &up->rangehigh) || 40 get_user(kp->flags, &up->flags) || 41 get_user(kp->mode, &up->mode) || 42 get_user(kp->signal, &up->signal)) 43 return -EFAULT; 44 return 0; 45} 46 47static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 48{ 49 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || 50 put_user(kp->tuner, &up->tuner) || 51 copy_to_user(up->name, kp->name, 32) || 52 put_user(kp->rangelow, &up->rangelow) || 53 put_user(kp->rangehigh, &up->rangehigh) || 54 put_user(kp->flags, &up->flags) || 55 put_user(kp->mode, &up->mode) || 56 put_user(kp->signal, &up->signal)) 57 return -EFAULT; 58 return 0; 59} 60 61 62struct video_buffer32 { 63 compat_caddr_t base; 64 compat_int_t height, width, depth, bytesperline; 65}; 66 67static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) 68{ 69 u32 tmp; 70 71 if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) || 72 get_user(tmp, &up->base) || 73 get_user(kp->height, &up->height) || 74 get_user(kp->width, &up->width) || 75 get_user(kp->depth, &up->depth) || 76 get_user(kp->bytesperline, &up->bytesperline)) 77 return -EFAULT; 78 79 /* This is actually a physical address stored 80 * as a void pointer. 81 */ 82 kp->base = (void *)(unsigned long) tmp; 83 84 return 0; 85} 86 87static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up) 88{ 89 u32 tmp = (u32)((unsigned long)kp->base); 90 91 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) || 92 put_user(tmp, &up->base) || 93 put_user(kp->height, &up->height) || 94 put_user(kp->width, &up->width) || 95 put_user(kp->depth, &up->depth) || 96 put_user(kp->bytesperline, &up->bytesperline)) 97 return -EFAULT; 98 return 0; 99} 100 101struct video_clip32 { 102 s32 x, y, width, height; /* Its really s32 in videodev.h */ 103 compat_caddr_t next; 104}; 105 106struct video_window32 { 107 u32 x, y, width, height, chromakey, flags; 108 compat_caddr_t clips; 109 compat_int_t clipcount; 110}; 111#endif 112 113static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 114{ 115 int ret = -ENOIOCTLCMD; 116 117 if (file->f_op->unlocked_ioctl) 118 ret = file->f_op->unlocked_ioctl(file, cmd, arg); 119 else if (file->f_op->ioctl) { 120 lock_kernel(); 121 ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); 122 unlock_kernel(); 123 } 124 125 return ret; 126} 127 128 129#ifdef CONFIG_VIDEO_V4L1_COMPAT 130/* You get back everything except the clips... */ 131static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) 132{ 133 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || 134 put_user(kp->x, &up->x) || 135 put_user(kp->y, &up->y) || 136 put_user(kp->width, &up->width) || 137 put_user(kp->height, &up->height) || 138 put_user(kp->chromakey, &up->chromakey) || 139 put_user(kp->flags, &up->flags) || 140 put_user(kp->clipcount, &up->clipcount)) 141 return -EFAULT; 142 return 0; 143} 144#endif 145 146struct v4l2_clip32 147{ 148 struct v4l2_rect c; 149 compat_caddr_t next; 150}; 151 152struct v4l2_window32 153{ 154 struct v4l2_rect w; 155 enum v4l2_field field; 156 __u32 chromakey; 157 compat_caddr_t clips; /* actually struct v4l2_clip32 * */ 158 __u32 clipcount; 159 compat_caddr_t bitmap; 160}; 161 162static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 163{ 164 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || 165 copy_from_user(&kp->w, &up->w, sizeof(up->w)) || 166 get_user(kp->field, &up->field) || 167 get_user(kp->chromakey, &up->chromakey) || 168 get_user(kp->clipcount, &up->clipcount)) 169 return -EFAULT; 170 if (kp->clipcount > 2048) 171 return -EINVAL; 172 if (kp->clipcount) { 173 struct v4l2_clip32 __user *uclips; 174 struct v4l2_clip __user *kclips; 175 int n = kp->clipcount; 176 compat_caddr_t p; 177 178 if (get_user(p, &up->clips)) 179 return -EFAULT; 180 uclips = compat_ptr(p); 181 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 182 kp->clips = kclips; 183 while (--n >= 0) { 184 if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) 185 return -EFAULT; 186 if (put_user(n ? kclips + 1 : NULL, &kclips->next)) 187 return -EFAULT; 188 uclips += 1; 189 kclips += 1; 190 } 191 } else 192 kp->clips = NULL; 193 return 0; 194} 195 196static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 197{ 198 if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || 199 put_user(kp->field, &up->field) || 200 put_user(kp->chromakey, &up->chromakey) || 201 put_user(kp->clipcount, &up->clipcount)) 202 return -EFAULT; 203 return 0; 204} 205 206static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 207{ 208 if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) 209 return -EFAULT; 210 return 0; 211} 212 213static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 214{ 215 if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) 216 return -EFAULT; 217 return 0; 218} 219 220static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 221{ 222 if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) 223 return -EFAULT; 224 return 0; 225} 226 227static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 228{ 229 if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) 230 return -EFAULT; 231 return 0; 232} 233 234struct v4l2_format32 235{ 236 enum v4l2_buf_type type; 237 union 238 { 239 struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE 240 struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY 241 struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE 242 __u8 raw_data[200]; // user-defined 243 } fmt; 244}; 245 246static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 247{ 248 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || 249 get_user(kp->type, &up->type)) 250 return -EFAULT; 251 switch (kp->type) { 252 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 253 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 254 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 255 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); 256 case V4L2_BUF_TYPE_VBI_CAPTURE: 257 return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 258 default: 259 printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n", 260 kp->type); 261 return -ENXIO; 262 } 263} 264 265static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 266{ 267 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || 268 put_user(kp->type, &up->type)) 269 return -EFAULT; 270 switch (kp->type) { 271 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 272 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 273 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 274 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); 275 case V4L2_BUF_TYPE_VBI_CAPTURE: 276 return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 277 default: 278 return -ENXIO; 279 } 280} 281 282static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 283{ 284 if (copy_from_user(kp, up, sizeof(struct v4l2_standard))) 285 return -EFAULT; 286 return 0; 287 288} 289 290static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 291{ 292 if (copy_to_user(up, kp, sizeof(struct v4l2_standard))) 293 return -EFAULT; 294 return 0; 295} 296 297struct v4l2_standard32 298{ 299 __u32 index; 300 __u32 id[2]; /* __u64 would get the alignment wrong */ 301 __u8 name[24]; 302 struct v4l2_fract frameperiod; /* Frames, not fields */ 303 __u32 framelines; 304 __u32 reserved[4]; 305}; 306 307static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 308{ 309 /* other fields are not set by the user, nor used by the driver */ 310 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || 311 get_user(kp->index, &up->index)) 312 return -EFAULT; 313 return 0; 314} 315 316static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) 317{ 318 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || 319 put_user(kp->index, &up->index) || 320 copy_to_user(up->id, &kp->id, sizeof(__u64)) || 321 copy_to_user(up->name, kp->name, 24) || 322 copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || 323 put_user(kp->framelines, &up->framelines) || 324 copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) 325 return -EFAULT; 326 return 0; 327} 328 329static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) 330{ 331 if (copy_from_user(kp, up, sizeof(struct v4l2_tuner))) 332 return -EFAULT; 333 return 0; 334 335} 336 337static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) 338{ 339 if (copy_to_user(up, kp, sizeof(struct v4l2_tuner))) 340 return -EFAULT; 341 return 0; 342} 343 344struct v4l2_buffer32 345{ 346 __u32 index; 347 enum v4l2_buf_type type; 348 __u32 bytesused; 349 __u32 flags; 350 enum v4l2_field field; 351 struct compat_timeval timestamp; 352 struct v4l2_timecode timecode; 353 __u32 sequence; 354 355 /* memory location */ 356 enum v4l2_memory memory; 357 union { 358 __u32 offset; 359 compat_long_t userptr; 360 } m; 361 __u32 length; 362 __u32 input; 363 __u32 reserved; 364}; 365 366static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 367{ 368 369 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 370 get_user(kp->index, &up->index) || 371 get_user(kp->type, &up->type) || 372 get_user(kp->flags, &up->flags) || 373 get_user(kp->memory, &up->memory) || 374 get_user(kp->input, &up->input)) 375 return -EFAULT; 376 switch(kp->memory) { 377 case V4L2_MEMORY_MMAP: 378 break; 379 case V4L2_MEMORY_USERPTR: 380 { 381 compat_long_t tmp; 382 383 if (get_user(kp->length, &up->length) || 384 get_user(tmp, &up->m.userptr)) 385 return -EFAULT; 386 387 kp->m.userptr = (unsigned long)compat_ptr(tmp); 388 } 389 break; 390 case V4L2_MEMORY_OVERLAY: 391 if(get_user(kp->m.offset, &up->m.offset)) 392 return -EFAULT; 393 break; 394 } 395 return 0; 396} 397 398static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 399{ 400 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) || 401 put_user(kp->index, &up->index) || 402 put_user(kp->type, &up->type) || 403 put_user(kp->flags, &up->flags) || 404 put_user(kp->memory, &up->memory) || 405 put_user(kp->input, &up->input)) 406 return -EFAULT; 407 switch(kp->memory) { 408 case V4L2_MEMORY_MMAP: 409 if (put_user(kp->length, &up->length) || 410 put_user(kp->m.offset, &up->m.offset)) 411 return -EFAULT; 412 break; 413 case V4L2_MEMORY_USERPTR: 414 if (put_user(kp->length, &up->length) || 415 put_user(kp->m.userptr, &up->m.userptr)) 416 return -EFAULT; 417 break; 418 case V4L2_MEMORY_OVERLAY: 419 if (put_user(kp->m.offset, &up->m.offset)) 420 return -EFAULT; 421 break; 422 } 423 if (put_user(kp->bytesused, &up->bytesused) || 424 put_user(kp->field, &up->field) || 425 put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || 426 put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) || 427 copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || 428 put_user(kp->sequence, &up->sequence) || 429 put_user(kp->reserved, &up->reserved)) 430 return -EFAULT; 431 return 0; 432} 433 434struct v4l2_framebuffer32 435{ 436 __u32 capability; 437 __u32 flags; 438 compat_caddr_t base; 439 struct v4l2_pix_format fmt; 440}; 441 442static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 443{ 444 u32 tmp; 445 446 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) || 447 get_user(tmp, &up->base) || 448 get_user(kp->capability, &up->capability) || 449 get_user(kp->flags, &up->flags)) 450 return -EFAULT; 451 kp->base = compat_ptr(tmp); 452 get_v4l2_pix_format(&kp->fmt, &up->fmt); 453 return 0; 454} 455 456static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up) 457{ 458 u32 tmp = (u32)((unsigned long)kp->base); 459 460 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) || 461 put_user(tmp, &up->base) || 462 put_user(kp->capability, &up->capability) || 463 put_user(kp->flags, &up->flags)) 464 return -EFAULT; 465 put_v4l2_pix_format(&kp->fmt, &up->fmt); 466 return 0; 467} 468 469static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) 470{ 471 if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) 472 return -EFAULT; 473 return 0; 474} 475 476static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) 477{ 478 if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) 479 return -EFAULT; 480 return 0; 481} 482 483static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 484{ 485 if (copy_from_user(kp, up, sizeof(struct v4l2_input))) 486 return -EFAULT; 487 return 0; 488} 489 490static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 491{ 492 if (copy_to_user(up, kp, sizeof(struct v4l2_input))) 493 return -EFAULT; 494 return 0; 495} 496 497#ifdef CONFIG_VIDEO_V4L1_COMPAT 498struct video_code32 499{ 500 char loadwhat[16]; /* name or tag of file being passed */ 501 compat_int_t datasize; 502 unsigned char *data; 503}; 504 505static inline int microcode32(struct video_code *kp, struct video_code32 __user *up) 506{ 507 if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || 508 copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) || 509 get_user(kp->datasize, &up->datasize) || 510 copy_from_user(kp->data, up->data, up->datasize)) 511 return -EFAULT; 512 return 0; 513} 514 515#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) 516#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) 517#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) 518#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) 519#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) 520#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) 521#define VIDIOCGFREQ32 _IOR('v',14, u32) 522#define VIDIOCSFREQ32 _IOW('v',15, u32) 523#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32) 524 525#endif 526 527/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ 528#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4) 529#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) 530#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) 531#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) 532#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 533#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 534/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */ 535#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t) 536#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32) 537#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32) 538#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) 539#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) 540#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) 541/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ 542#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) 543#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) 544#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) 545#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) 546 547#ifdef CONFIG_VIDEO_V4L1_COMPAT 548enum { 549 MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) 550}; 551 552static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) 553{ 554 struct video_window32 __user *up = compat_ptr(arg); 555 struct video_window __user *vw; 556 struct video_clip __user *p; 557 int nclips; 558 u32 n; 559 560 if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) 561 return -EFAULT; 562 563 if (get_user(nclips, &up->clipcount)) 564 return -EFAULT; 565 566 /* Peculiar interface... */ 567 if (nclips < 0) 568 nclips = VIDEO_CLIPMAP_SIZE; 569 570 if (nclips > MaxClips) 571 return -ENOMEM; 572 573 vw = compat_alloc_user_space(sizeof(struct video_window) + 574 nclips * sizeof(struct video_clip)); 575 576 p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; 577 578 if (get_user(n, &up->x) || put_user(n, &vw->x) || 579 get_user(n, &up->y) || put_user(n, &vw->y) || 580 get_user(n, &up->width) || put_user(n, &vw->width) || 581 get_user(n, &up->height) || put_user(n, &vw->height) || 582 get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || 583 get_user(n, &up->flags) || put_user(n, &vw->flags) || 584 get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || 585 get_user(n, &up->clips) || put_user(p, &vw->clips)) 586 return -EFAULT; 587 588 if (nclips) { 589 struct video_clip32 __user *u = compat_ptr(n); 590 int i; 591 if (!u) 592 return -EINVAL; 593 for (i = 0; i < nclips; i++, u++, p++) { 594 s32 v; 595 if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) || 596 !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) || 597 get_user(v, &u->x) || 598 put_user(v, &p->x) || 599 get_user(v, &u->y) || 600 put_user(v, &p->y) || 601 get_user(v, &u->width) || 602 put_user(v, &p->width) || 603 get_user(v, &u->height) || 604 put_user(v, &p->height) || 605 put_user(NULL, &p->next)) 606 return -EFAULT; 607 } 608 } 609 610 return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); 611} 612#endif 613 614static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 615{ 616 union { 617#ifdef CONFIG_VIDEO_V4L1_COMPAT 618 struct video_tuner vt; 619 struct video_buffer vb; 620 struct video_window vw; 621 struct video_code vc; 622 struct video_audio va; 623#endif 624 struct v4l2_format v2f; 625 struct v4l2_buffer v2b; 626 struct v4l2_framebuffer v2fb; 627 struct v4l2_standard v2s; 628 struct v4l2_input v2i; 629 struct v4l2_tuner v2t; 630 unsigned long vx; 631 } karg; 632 void __user *up = compat_ptr(arg); 633 int compatible_arg = 1; 634 int err = 0; 635 int realcmd = cmd; 636 637 /* First, convert the command. */ 638 switch(cmd) { 639#ifdef CONFIG_VIDEO_V4L1_COMPAT 640 case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break; 641 case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break; 642 case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break; 643 case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break; 644 case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break; 645 case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break; 646 case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break; 647 case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break; 648#endif 649 case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break; 650 case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break; 651 case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break; 652 case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break; 653 case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break; 654 case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break; 655 case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break; 656 case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break; 657 case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break; 658 case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break; 659 case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break; 660 case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break; 661 case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break; 662 case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break; 663 case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break; 664 case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break; 665 }; 666 667 switch(cmd) { 668#ifdef CONFIG_VIDEO_V4L1_COMPAT 669 case VIDIOCSTUNER: 670 case VIDIOCGTUNER: 671 err = get_video_tuner32(&karg.vt, up); 672 compatible_arg = 0; 673 674 break; 675 676 case VIDIOCSFBUF: 677 err = get_video_buffer32(&karg.vb, up); 678 compatible_arg = 0; 679 break; 680 681 682 case VIDIOCSFREQ: 683#endif 684 case VIDIOC_S_INPUT: 685 case VIDIOC_OVERLAY: 686 case VIDIOC_STREAMON: 687 case VIDIOC_STREAMOFF: 688 err = get_user(karg.vx, (u32 __user *)up); 689 compatible_arg = 1; 690 break; 691 692 case VIDIOC_S_FBUF: 693 err = get_v4l2_framebuffer32(&karg.v2fb, up); 694 compatible_arg = 0; 695 break; 696 697 case VIDIOC_G_FMT: 698 case VIDIOC_S_FMT: 699 case VIDIOC_TRY_FMT: 700 err = get_v4l2_format32(&karg.v2f, up); 701 compatible_arg = 0; 702 break; 703 704 case VIDIOC_QUERYBUF: 705 case VIDIOC_QBUF: 706 case VIDIOC_DQBUF: 707 err = get_v4l2_buffer32(&karg.v2b, up); 708 compatible_arg = 0; 709 break; 710 711 case VIDIOC_ENUMSTD: 712 err = get_v4l2_standard(&karg.v2s, up); 713 compatible_arg = 0; 714 break; 715 716 case VIDIOC_ENUMSTD32: 717 err = get_v4l2_standard32(&karg.v2s, up); 718 compatible_arg = 0; 719 break; 720 721 case VIDIOC_ENUMINPUT: 722 err = get_v4l2_input(&karg.v2i, up); 723 compatible_arg = 0; 724 break; 725 726 case VIDIOC_ENUMINPUT32: 727 err = get_v4l2_input32(&karg.v2i, up); 728 compatible_arg = 0; 729 break; 730 731 case VIDIOC_G_TUNER: 732 case VIDIOC_S_TUNER: 733 err = get_v4l2_tuner(&karg.v2t, up); 734 compatible_arg = 0; 735 break; 736 737#ifdef CONFIG_VIDEO_V4L1_COMPAT 738 case VIDIOCGWIN: 739 case VIDIOCGFBUF: 740 case VIDIOCGFREQ: 741#endif 742 case VIDIOC_G_FBUF: 743 case VIDIOC_G_INPUT: 744 compatible_arg = 0; 745 break; 746#ifdef CONFIG_VIDEO_V4L1_COMPAT 747 case VIDIOCSMICROCODE: 748 err = microcode32(&karg.vc, up); 749 compatible_arg = 0; 750 break; 751#endif 752 }; 753 if(err) 754 goto out; 755 756 if(compatible_arg) 757 err = native_ioctl(file, realcmd, (unsigned long)up); 758 else { 759 mm_segment_t old_fs = get_fs(); 760 761 set_fs(KERNEL_DS); 762 err = native_ioctl(file, realcmd, (unsigned long) &karg); 763 set_fs(old_fs); 764 } 765 if(err == 0) { 766 switch(cmd) { 767#ifdef CONFIG_VIDEO_V4L1_COMPAT 768 case VIDIOCGTUNER: 769 err = put_video_tuner32(&karg.vt, up); 770 break; 771 772 case VIDIOCGWIN: 773 err = put_video_window32(&karg.vw, up); 774 break; 775 776 case VIDIOCGFBUF: 777 err = put_video_buffer32(&karg.vb, up); 778 break; 779 780#endif 781 case VIDIOC_G_FBUF: 782 err = put_v4l2_framebuffer32(&karg.v2fb, up); 783 break; 784 785 case VIDIOC_G_FMT: 786 case VIDIOC_S_FMT: 787 case VIDIOC_TRY_FMT: 788 err = put_v4l2_format32(&karg.v2f, up); 789 break; 790 791 case VIDIOC_QUERYBUF: 792 case VIDIOC_QBUF: 793 case VIDIOC_DQBUF: 794 err = put_v4l2_buffer32(&karg.v2b, up); 795 break; 796 797 case VIDIOC_ENUMSTD: 798 err = put_v4l2_standard(&karg.v2s, up); 799 break; 800 801 case VIDIOC_ENUMSTD32: 802 err = put_v4l2_standard32(&karg.v2s, up); 803 break; 804 805 case VIDIOC_G_TUNER: 806 case VIDIOC_S_TUNER: 807 err = put_v4l2_tuner(&karg.v2t, up); 808 break; 809 810 case VIDIOC_ENUMINPUT: 811 err = put_v4l2_input(&karg.v2i, up); 812 break; 813 814 case VIDIOC_ENUMINPUT32: 815 err = put_v4l2_input32(&karg.v2i, up); 816 break; 817 818#ifdef CONFIG_VIDEO_V4L1_COMPAT 819 case VIDIOCGFREQ: 820#endif 821 case VIDIOC_G_INPUT: 822 err = put_user(((u32)karg.vx), (u32 __user *)up); 823 break; 824 }; 825 } 826out: 827 return err; 828} 829 830long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 831{ 832 int ret = -ENOIOCTLCMD; 833 834 if (!file->f_op->ioctl) 835 return ret; 836 837 switch (cmd) { 838#ifdef CONFIG_VIDEO_V4L1_COMPAT 839 case VIDIOCSWIN32: 840 ret = do_set_window(file, cmd, arg); 841 break; 842 case VIDIOCGTUNER32: 843 case VIDIOCSTUNER32: 844 case VIDIOCGWIN32: 845 case VIDIOCGFBUF32: 846 case VIDIOCSFBUF32: 847 case VIDIOCGFREQ32: 848 case VIDIOCSFREQ32: 849 case VIDIOCGAUDIO: 850 case VIDIOCSAUDIO: 851#endif 852 case VIDIOC_QUERYCAP: 853 case VIDIOC_ENUM_FMT: 854 case VIDIOC_G_FMT32: 855 case VIDIOC_CROPCAP: 856 case VIDIOC_S_CROP: 857 case VIDIOC_S_FMT32: 858 case VIDIOC_REQBUFS: 859 case VIDIOC_QUERYBUF32: 860 case VIDIOC_G_FBUF32: 861 case VIDIOC_S_FBUF32: 862 case VIDIOC_OVERLAY32: 863 case VIDIOC_QBUF32: 864 case VIDIOC_DQBUF32: 865 case VIDIOC_STREAMON32: 866 case VIDIOC_STREAMOFF32: 867 case VIDIOC_G_PARM: 868 case VIDIOC_G_STD: 869 case VIDIOC_S_STD: 870 case VIDIOC_G_TUNER: 871 case VIDIOC_S_TUNER: 872 case VIDIOC_ENUMSTD: 873 case VIDIOC_ENUMSTD32: 874 case VIDIOC_ENUMINPUT: 875 case VIDIOC_ENUMINPUT32: 876 case VIDIOC_G_CTRL: 877 case VIDIOC_S_CTRL32: 878 case VIDIOC_QUERYCTRL: 879 case VIDIOC_G_INPUT32: 880 case VIDIOC_S_INPUT32: 881 case VIDIOC_TRY_FMT32: 882 ret = do_video_ioctl(file, cmd, arg); 883 break; 884 885#ifdef CONFIG_VIDEO_V4L1_COMPAT 886 /* Little v, the video4linux ioctls (conflict?) */ 887 case VIDIOCGCAP: 888 case VIDIOCGCHAN: 889 case VIDIOCSCHAN: 890 case VIDIOCGPICT: 891 case VIDIOCSPICT: 892 case VIDIOCCAPTURE: 893 case VIDIOCKEY: 894 case VIDIOCSYNC: 895 case VIDIOCMCAPTURE: 896 case VIDIOCGMBUF: 897 case VIDIOCGUNIT: 898 case VIDIOCGCAPTURE: 899 case VIDIOCSCAPTURE: 900 901 /* BTTV specific... */ 902 case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): 903 case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): 904 case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): 905 case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ 906 case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): 907 case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): 908 case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): 909 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): 910 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 911 break; 912#endif 913 default: 914 v4l_print_ioctl("compat_ioctl32", cmd); 915 } 916 return ret; 917} 918#else 919long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 920{ 921 return -ENOIOCTLCMD; 922} 923#endif 924EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); 925 926MODULE_LICENSE("GPL");