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.16-rc2 879 lines 24 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/config.h> 16#include <linux/compat.h> 17#include <linux/videodev.h> 18#include <linux/videodev2.h> 19#include <linux/module.h> 20#include <linux/smp_lock.h> 21#include <media/v4l2-common.h> 22 23#ifdef CONFIG_COMPAT 24 25 26struct video_tuner32 { 27 compat_int_t tuner; 28 char name[32]; 29 compat_ulong_t rangelow, rangehigh; 30 u32 flags; /* It is really u32 in videodev.h */ 31 u16 mode, signal; 32}; 33 34static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 35{ 36 if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) || 37 get_user(kp->tuner, &up->tuner) || 38 copy_from_user(kp->name, up->name, 32) || 39 get_user(kp->rangelow, &up->rangelow) || 40 get_user(kp->rangehigh, &up->rangehigh) || 41 get_user(kp->flags, &up->flags) || 42 get_user(kp->mode, &up->mode) || 43 get_user(kp->signal, &up->signal)) 44 return -EFAULT; 45 return 0; 46} 47 48static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up) 49{ 50 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) || 51 put_user(kp->tuner, &up->tuner) || 52 copy_to_user(up->name, kp->name, 32) || 53 put_user(kp->rangelow, &up->rangelow) || 54 put_user(kp->rangehigh, &up->rangehigh) || 55 put_user(kp->flags, &up->flags) || 56 put_user(kp->mode, &up->mode) || 57 put_user(kp->signal, &up->signal)) 58 return -EFAULT; 59 return 0; 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 112static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 113{ 114 int ret = -ENOIOCTLCMD; 115 116 if (file->f_op->unlocked_ioctl) 117 ret = file->f_op->unlocked_ioctl(file, cmd, arg); 118 else if (file->f_op->ioctl) { 119 lock_kernel(); 120 ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); 121 unlock_kernel(); 122 } 123 124 return ret; 125} 126 127 128/* You get back everything except the clips... */ 129static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) 130{ 131 if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) || 132 put_user(kp->x, &up->x) || 133 put_user(kp->y, &up->y) || 134 put_user(kp->width, &up->width) || 135 put_user(kp->height, &up->height) || 136 put_user(kp->chromakey, &up->chromakey) || 137 put_user(kp->flags, &up->flags) || 138 put_user(kp->clipcount, &up->clipcount)) 139 return -EFAULT; 140 return 0; 141} 142 143struct v4l2_clip32 144{ 145 struct v4l2_rect c; 146 compat_caddr_t next; 147}; 148 149struct v4l2_window32 150{ 151 struct v4l2_rect w; 152 enum v4l2_field field; 153 __u32 chromakey; 154 compat_caddr_t clips; /* actually struct v4l2_clip32 * */ 155 __u32 clipcount; 156 compat_caddr_t bitmap; 157}; 158 159static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 160{ 161 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || 162 copy_from_user(&kp->w, &up->w, sizeof(up->w)) || 163 get_user(kp->field, &up->field) || 164 get_user(kp->chromakey, &up->chromakey) || 165 get_user(kp->clipcount, &up->clipcount)) 166 return -EFAULT; 167 if (kp->clipcount > 2048) 168 return -EINVAL; 169 if (kp->clipcount) { 170 struct v4l2_clip32 *uclips = compat_ptr(up->clips); 171 struct v4l2_clip *kclips; 172 int n = kp->clipcount; 173 174 kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); 175 kp->clips = kclips; 176 while (--n >= 0) { 177 if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) || 178 copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c))) 179 return -EFAULT; 180 kclips->next = n ? kclips + 1 : 0; 181 uclips += 1; 182 kclips += 1; 183 } 184 } else 185 kp->clips = 0; 186 return 0; 187} 188 189static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) 190{ 191 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) || 192 copy_to_user(&up->w, &kp->w, sizeof(up->w)) || 193 put_user(kp->field, &up->field) || 194 put_user(kp->chromakey, &up->chromakey) || 195 put_user(kp->clipcount, &up->clipcount)) 196 return -EFAULT; 197 return 0; 198} 199 200static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 201{ 202 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) || 203 copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) 204 return -EFAULT; 205 return 0; 206} 207 208static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) 209{ 210 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) || 211 copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) 212 return -EFAULT; 213 return 0; 214} 215 216static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 217{ 218 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) || 219 copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) 220 return -EFAULT; 221 return 0; 222} 223 224static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) 225{ 226 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) || 227 copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) 228 return -EFAULT; 229 return 0; 230} 231 232struct v4l2_format32 233{ 234 enum v4l2_buf_type type; 235 union 236 { 237 struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE 238 struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY 239 struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE 240 __u8 raw_data[200]; // user-defined 241 } fmt; 242}; 243 244static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 245{ 246 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) || 247 get_user(kp->type, &up->type)) 248 return -EFAULT; 249 switch (kp->type) { 250 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 251 return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 252 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 253 return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); 254 case V4L2_BUF_TYPE_VBI_CAPTURE: 255 return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 256 default: 257 printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n", 258 kp->type); 259 return -ENXIO; 260 } 261} 262 263static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) 264{ 265 if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || 266 put_user(kp->type, &up->type)) 267 return -EFAULT; 268 switch (kp->type) { 269 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 270 return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); 271 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 272 return put_v4l2_window32(&kp->fmt.win, &up->fmt.win); 273 case V4L2_BUF_TYPE_VBI_CAPTURE: 274 return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); 275 default: 276 return -ENXIO; 277 } 278} 279 280static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 281{ 282 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) || 283 copy_from_user(kp, up, sizeof(struct v4l2_standard))) 284 return -EFAULT; 285 return 0; 286 287} 288 289static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up) 290{ 291 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) || 292 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 (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) || 332 copy_from_user(kp, up, sizeof(struct v4l2_tuner))) 333 return -EFAULT; 334 return 0; 335 336} 337 338static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up) 339{ 340 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) || 341 copy_to_user(up, kp, sizeof(struct v4l2_tuner))) 342 return -EFAULT; 343 return 0; 344} 345 346struct v4l2_buffer32 347{ 348 __u32 index; 349 enum v4l2_buf_type type; 350 __u32 bytesused; 351 __u32 flags; 352 enum v4l2_field field; 353 struct compat_timeval timestamp; 354 struct v4l2_timecode timecode; 355 __u32 sequence; 356 357 /* memory location */ 358 enum v4l2_memory memory; 359 union { 360 __u32 offset; 361 compat_long_t userptr; 362 } m; 363 __u32 length; 364 __u32 input; 365 __u32 reserved; 366}; 367 368static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up) 369{ 370 371 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) || 372 get_user(kp->index, &up->index) || 373 get_user(kp->type, &up->type) || 374 get_user(kp->flags, &up->flags) || 375 get_user(kp->memory, &up->memory) || 376 get_user(kp->input, &up->input)) 377 return -EFAULT; 378 switch(kp->memory) { 379 case V4L2_MEMORY_MMAP: 380 break; 381 case V4L2_MEMORY_USERPTR: 382 { 383 unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr); 384 385 if(get_user(kp->length, &up->length) || 386 get_user(kp->m.userptr, &tmp)) 387 return -EFAULT; 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 (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) || 472 copy_from_user(kp, up, sizeof(struct v4l2_input) - 4)) 473 return -EFAULT; 474 return 0; 475} 476 477static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up) 478{ 479 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) || 480 copy_to_user(up, kp, sizeof(struct v4l2_input) - 4)) 481 return -EFAULT; 482 return 0; 483} 484 485static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 486{ 487 if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) || 488 copy_from_user(kp, up, sizeof(struct v4l2_input))) 489 return -EFAULT; 490 return 0; 491} 492 493static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up) 494{ 495 if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) || 496 copy_to_user(up, kp, sizeof(struct v4l2_input))) 497 return -EFAULT; 498 return 0; 499} 500 501#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) 502#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) 503#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) 504#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) 505#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) 506#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) 507#define VIDIOCGFREQ32 _IOR('v',14, u32) 508#define VIDIOCSFREQ32 _IOW('v',15, u32) 509 510/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ 511#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4) 512#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32) 513#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32) 514#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32) 515#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32) 516#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32) 517/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */ 518#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t) 519#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32) 520#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32) 521#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t) 522#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t) 523#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32) 524/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */ 525#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control) 526#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t) 527#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) 528#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) 529 530enum { 531 MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) 532}; 533 534static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) 535{ 536 struct video_window32 __user *up = compat_ptr(arg); 537 struct video_window __user *vw; 538 struct video_clip __user *p; 539 int nclips; 540 u32 n; 541 542 if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32))) 543 return -EFAULT; 544 545 if (get_user(nclips, &up->clipcount)) 546 return -EFAULT; 547 548 /* Peculiar interface... */ 549 if (nclips < 0) 550 nclips = VIDEO_CLIPMAP_SIZE; 551 552 if (nclips > MaxClips) 553 return -ENOMEM; 554 555 vw = compat_alloc_user_space(sizeof(struct video_window) + 556 nclips * sizeof(struct video_clip)); 557 558 p = nclips ? (struct video_clip __user *)(vw + 1) : NULL; 559 560 if (get_user(n, &up->x) || put_user(n, &vw->x) || 561 get_user(n, &up->y) || put_user(n, &vw->y) || 562 get_user(n, &up->width) || put_user(n, &vw->width) || 563 get_user(n, &up->height) || put_user(n, &vw->height) || 564 get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) || 565 get_user(n, &up->flags) || put_user(n, &vw->flags) || 566 get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) || 567 get_user(n, &up->clips) || put_user(p, &vw->clips)) 568 return -EFAULT; 569 570 if (nclips) { 571 struct video_clip32 __user *u = compat_ptr(n); 572 int i; 573 if (!u) 574 return -EINVAL; 575 for (i = 0; i < nclips; i++, u++, p++) { 576 s32 v; 577 if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) || 578 !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) || 579 get_user(v, &u->x) || 580 put_user(v, &p->x) || 581 get_user(v, &u->y) || 582 put_user(v, &p->y) || 583 get_user(v, &u->width) || 584 put_user(v, &p->width) || 585 get_user(v, &u->height) || 586 put_user(v, &p->height) || 587 put_user(NULL, &p->next)) 588 return -EFAULT; 589 } 590 } 591 592 return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); 593} 594 595static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 596{ 597 union { 598 struct video_tuner vt; 599 struct video_buffer vb; 600 struct video_window vw; 601 struct v4l2_format v2f; 602 struct v4l2_buffer v2b; 603 struct v4l2_framebuffer v2fb; 604 struct v4l2_standard v2s; 605 struct v4l2_input v2i; 606 struct v4l2_tuner v2t; 607 unsigned long vx; 608 } karg; 609 void __user *up = compat_ptr(arg); 610 int compatible_arg = 1; 611 int err = 0; 612 int realcmd = cmd; 613 614 /* First, convert the command. */ 615 switch(cmd) { 616 case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; 617 case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; 618 case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; 619 case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; 620 case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; 621 case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; 622 case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; 623 case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; 624 case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; 625 case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; 626 case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break; 627 case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break; 628 case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break; 629 case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break; 630 case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break; 631 case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break; 632 case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break; 633 case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break; 634 case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break; 635 case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break; 636 case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break; 637 case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break; 638 case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break; 639 }; 640 641 switch(cmd) { 642 case VIDIOCSTUNER: 643 case VIDIOCGTUNER: 644 err = get_video_tuner32(&karg.vt, up); 645 compatible_arg = 0; 646 647 break; 648 649 case VIDIOCSFBUF: 650 err = get_video_buffer32(&karg.vb, up); 651 compatible_arg = 0; 652 break; 653 654 case VIDIOCSFREQ: 655 case VIDIOC_S_INPUT: 656 case VIDIOC_OVERLAY: 657 case VIDIOC_STREAMON: 658 case VIDIOC_STREAMOFF: 659 err = get_user(karg.vx, (u32 __user *)up); 660 compatible_arg = 0; 661 break; 662 663 case VIDIOC_S_FBUF: 664 err = get_v4l2_framebuffer32(&karg.v2fb, up); 665 compatible_arg = 0; 666 break; 667 668 case VIDIOC_G_FMT: 669 case VIDIOC_S_FMT: 670 case VIDIOC_TRY_FMT: 671 err = get_v4l2_format32(&karg.v2f, up); 672 compatible_arg = 0; 673 break; 674 675 case VIDIOC_QUERYBUF: 676 case VIDIOC_QBUF: 677 case VIDIOC_DQBUF: 678 err = get_v4l2_buffer32(&karg.v2b, up); 679 compatible_arg = 0; 680 break; 681 682 case VIDIOC_ENUMSTD: 683 err = get_v4l2_standard(&karg.v2s, up); 684 compatible_arg = 0; 685 break; 686 687 case VIDIOC_ENUMSTD32: 688 err = get_v4l2_standard32(&karg.v2s, up); 689 compatible_arg = 0; 690 break; 691 692 case VIDIOC_ENUMINPUT: 693 err = get_v4l2_input(&karg.v2i, up); 694 compatible_arg = 0; 695 break; 696 697 case VIDIOC_ENUMINPUT32: 698 err = get_v4l2_input32(&karg.v2i, up); 699 compatible_arg = 0; 700 break; 701 702 case VIDIOC_G_TUNER: 703 case VIDIOC_S_TUNER: 704 err = get_v4l2_tuner(&karg.v2t, up); 705 compatible_arg = 0; 706 break; 707 708 case VIDIOCGWIN: 709 case VIDIOCGFBUF: 710 case VIDIOCGFREQ: 711 case VIDIOC_G_FBUF: 712 case VIDIOC_G_INPUT: 713 compatible_arg = 0; 714 }; 715 716 if(err) 717 goto out; 718 719 if(compatible_arg) 720 err = native_ioctl(file, realcmd, (unsigned long)up); 721 else { 722 mm_segment_t old_fs = get_fs(); 723 724 set_fs(KERNEL_DS); 725 err = native_ioctl(file, realcmd, (unsigned long)&karg); 726 set_fs(old_fs); 727 } 728 if(err == 0) { 729 switch(cmd) { 730 case VIDIOCGTUNER: 731 err = put_video_tuner32(&karg.vt, up); 732 break; 733 734 case VIDIOCGWIN: 735 err = put_video_window32(&karg.vw, up); 736 break; 737 738 case VIDIOCGFBUF: 739 err = put_video_buffer32(&karg.vb, up); 740 break; 741 742 case VIDIOC_G_FBUF: 743 err = put_v4l2_framebuffer32(&karg.v2fb, up); 744 break; 745 746 case VIDIOC_G_FMT: 747 case VIDIOC_S_FMT: 748 case VIDIOC_TRY_FMT: 749 err = put_v4l2_format32(&karg.v2f, up); 750 break; 751 752 case VIDIOC_QUERYBUF: 753 case VIDIOC_QBUF: 754 case VIDIOC_DQBUF: 755 err = put_v4l2_buffer32(&karg.v2b, up); 756 break; 757 758 case VIDIOC_ENUMSTD: 759 err = put_v4l2_standard(&karg.v2s, up); 760 break; 761 762 case VIDIOC_ENUMSTD32: 763 err = put_v4l2_standard32(&karg.v2s, up); 764 break; 765 766 case VIDIOC_G_TUNER: 767 case VIDIOC_S_TUNER: 768 err = put_v4l2_tuner(&karg.v2t, up); 769 break; 770 771 case VIDIOC_ENUMINPUT: 772 err = put_v4l2_input(&karg.v2i, up); 773 break; 774 775 case VIDIOC_ENUMINPUT32: 776 err = put_v4l2_input32(&karg.v2i, up); 777 break; 778 779 case VIDIOCGFREQ: 780 case VIDIOC_G_INPUT: 781 err = put_user(((u32)karg.vx), (u32 __user *)up); 782 break; 783 }; 784 } 785out: 786 return err; 787} 788 789long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 790{ 791 int ret = -ENOIOCTLCMD; 792 793 if (!file->f_op->ioctl) 794 return ret; 795 796 switch (cmd) { 797 case VIDIOCSWIN32: 798 ret = do_set_window(file, cmd, arg); 799 break; 800 case VIDIOCGTUNER32: 801 case VIDIOCSTUNER32: 802 case VIDIOCGWIN32: 803 case VIDIOCGFBUF32: 804 case VIDIOCSFBUF32: 805 case VIDIOCGFREQ32: 806 case VIDIOCSFREQ32: 807 case VIDIOC_QUERYCAP: 808 case VIDIOC_ENUM_FMT: 809 case VIDIOC_G_FMT32: 810 case VIDIOC_S_FMT32: 811 case VIDIOC_REQBUFS: 812 case VIDIOC_QUERYBUF32: 813 case VIDIOC_G_FBUF32: 814 case VIDIOC_S_FBUF32: 815 case VIDIOC_OVERLAY32: 816 case VIDIOC_QBUF32: 817 case VIDIOC_DQBUF32: 818 case VIDIOC_STREAMON32: 819 case VIDIOC_STREAMOFF32: 820 case VIDIOC_G_PARM: 821 case VIDIOC_G_STD: 822 case VIDIOC_S_STD: 823 case VIDIOC_G_TUNER: 824 case VIDIOC_S_TUNER: 825 case VIDIOC_ENUMSTD: 826 case VIDIOC_ENUMSTD32: 827 case VIDIOC_ENUMINPUT: 828 case VIDIOC_ENUMINPUT32: 829 case VIDIOC_G_CTRL: 830 case VIDIOC_S_CTRL32: 831 case VIDIOC_QUERYCTRL: 832 case VIDIOC_G_INPUT32: 833 case VIDIOC_S_INPUT32: 834 case VIDIOC_TRY_FMT32: 835 ret = do_video_ioctl(file, cmd, arg); 836 break; 837 838 /* Little v, the video4linux ioctls (conflict?) */ 839 case VIDIOCGCAP: 840 case VIDIOCGCHAN: 841 case VIDIOCSCHAN: 842 case VIDIOCGPICT: 843 case VIDIOCSPICT: 844 case VIDIOCCAPTURE: 845 case VIDIOCKEY: 846 case VIDIOCGAUDIO: 847 case VIDIOCSAUDIO: 848 case VIDIOCSYNC: 849 case VIDIOCMCAPTURE: 850 case VIDIOCGMBUF: 851 case VIDIOCGUNIT: 852 case VIDIOCGCAPTURE: 853 case VIDIOCSCAPTURE: 854 855 /* BTTV specific... */ 856 case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]): 857 case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]): 858 case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int): 859 case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */ 860 case _IOR('v' , BASE_VIDIOCPRIVATE+4, int): 861 case _IOR('v' , BASE_VIDIOCPRIVATE+5, int): 862 case _IOR('v' , BASE_VIDIOCPRIVATE+6, int): 863 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): 864 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 865 break; 866 default: 867 v4l_print_ioctl("compat_ioctl32", cmd); 868 } 869 return ret; 870} 871#else 872long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) 873{ 874 return -ENOIOCTLCMD; 875} 876#endif 877EXPORT_SYMBOL_GPL(v4l_compat_ioctl32); 878 879MODULE_LICENSE("GPL");