Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / drivers / media / video / v4l1-compat.c
1 /*
2  * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
3  *
4  *      Video for Linux Two
5  *      Backward Compatibility Layer
6  *
7  *      Support subroutines for providing V4L2 drivers with backward
8  *      compatibility with applications using the old API.
9  *
10  *      This program is free software; you can redistribute it and/or
11  *      modify it under the terms of the GNU General Public License
12  *      as published by the Free Software Foundation; either version
13  *      2 of the License, or (at your option) any later version.
14  *
15  * Author:      Bill Dirks <bdirks@pacbell.net>
16  *              et al.
17  *
18  */
19
20 #include <linux/config.h>
21
22 #include <linux/init.h>
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/types.h>
26 #include <linux/kernel.h>
27 #include <linux/sched.h>
28 #include <linux/smp_lock.h>
29 #include <linux/mm.h>
30 #include <linux/fs.h>
31 #include <linux/file.h>
32 #include <linux/string.h>
33 #include <linux/errno.h>
34 #include <linux/slab.h>
35 #include <linux/videodev.h>
36
37 #include <asm/uaccess.h>
38 #include <asm/system.h>
39 #include <asm/pgtable.h>
40
41 #ifdef CONFIG_KMOD
42 #include <linux/kmod.h>
43 #endif
44
45 static unsigned int debug  = 0;
46 module_param(debug, int, 0644);
47 MODULE_PARM_DESC(debug,"enable debug messages");
48 MODULE_AUTHOR("Bill Dirks");
49 MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
50 MODULE_LICENSE("GPL");
51
52 #define dprintk(fmt, arg...)    if (debug) \
53         printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
54
55 /*
56  *      I O C T L   T R A N S L A T I O N
57  *
58  *      From here on down is the code for translating the numerous
59  *      ioctl commands from the old API to the new API.
60  */
61
62 static int
63 get_v4l_control(struct inode            *inode,
64                 struct file             *file,
65                 int                     cid,
66                 v4l2_kioctl             drv)
67 {
68         struct v4l2_queryctrl   qctrl2;
69         struct v4l2_control     ctrl2;
70         int                     err;
71
72         qctrl2.id = cid;
73         err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
74         if (err < 0)
75                 dprintk("VIDIOC_QUERYCTRL: %d\n",err);
76         if (err == 0 &&
77             !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
78         {
79                 ctrl2.id = qctrl2.id;
80                 err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
81                 if (err < 0) {
82                         dprintk("VIDIOC_G_CTRL: %d\n",err);
83                         return 0;
84                 }
85                 return ((ctrl2.value - qctrl2.minimum) * 65535
86                          + (qctrl2.maximum - qctrl2.minimum) / 2)
87                         / (qctrl2.maximum - qctrl2.minimum);
88         }
89         return 0;
90 }
91
92 static int
93 set_v4l_control(struct inode            *inode,
94                 struct file             *file,
95                 int                     cid,
96                 int                     value,
97                 v4l2_kioctl             drv)
98 {
99         struct v4l2_queryctrl   qctrl2;
100         struct v4l2_control     ctrl2;
101         int                     err;
102
103         qctrl2.id = cid;
104         err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
105         if (err < 0)
106                 dprintk("VIDIOC_QUERYCTRL: %d\n",err);
107         if (err == 0 &&
108             !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
109             !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
110         {
111                 if (value < 0)
112                         value = 0;
113                 if (value > 65535)
114                         value = 65535;
115                 if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
116                         value = 65535;
117                 ctrl2.id = qctrl2.id;
118                 ctrl2.value =
119                         (value * (qctrl2.maximum - qctrl2.minimum)
120                          + 32767)
121                         / 65535;
122                 ctrl2.value += qctrl2.minimum;
123                 err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
124                 if (err < 0)
125                         dprintk("VIDIOC_S_CTRL: %d\n",err);
126         }
127         return 0;
128 }
129
130 /* ----------------------------------------------------------------- */
131
132 static int palette2pixelformat[] = {
133         [VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
134         [VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
135         [VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
136         [VIDEO_PALETTE_RGB24]   = V4L2_PIX_FMT_BGR24,
137         [VIDEO_PALETTE_RGB32]   = V4L2_PIX_FMT_BGR32,
138         /* yuv packed pixel */
139         [VIDEO_PALETTE_YUYV]    = V4L2_PIX_FMT_YUYV,
140         [VIDEO_PALETTE_YUV422]  = V4L2_PIX_FMT_YUYV,
141         [VIDEO_PALETTE_UYVY]    = V4L2_PIX_FMT_UYVY,
142         /* yuv planar */
143         [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
144         [VIDEO_PALETTE_YUV420]  = V4L2_PIX_FMT_YUV420,
145         [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
146         [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
147         [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
148 };
149
150 static unsigned int
151 palette_to_pixelformat(unsigned int palette)
152 {
153         if (palette < ARRAY_SIZE(palette2pixelformat))
154                 return palette2pixelformat[palette];
155         else
156                 return 0;
157 }
158
159 static unsigned int
160 pixelformat_to_palette(int pixelformat)
161 {
162         int     palette = 0;
163         switch (pixelformat)
164         {
165         case V4L2_PIX_FMT_GREY:
166                 palette = VIDEO_PALETTE_GREY;
167                 break;
168         case V4L2_PIX_FMT_RGB555:
169                 palette = VIDEO_PALETTE_RGB555;
170                 break;
171         case V4L2_PIX_FMT_RGB565:
172                 palette = VIDEO_PALETTE_RGB565;
173                 break;
174         case V4L2_PIX_FMT_BGR24:
175                 palette = VIDEO_PALETTE_RGB24;
176                 break;
177         case V4L2_PIX_FMT_BGR32:
178                 palette = VIDEO_PALETTE_RGB32;
179                 break;
180         /* yuv packed pixel */
181         case V4L2_PIX_FMT_YUYV:
182                 palette = VIDEO_PALETTE_YUYV;
183                 break;
184         case V4L2_PIX_FMT_UYVY:
185                 palette = VIDEO_PALETTE_UYVY;
186                 break;
187         /* yuv planar */
188         case V4L2_PIX_FMT_YUV410:
189                 palette = VIDEO_PALETTE_YUV420;
190                 break;
191         case V4L2_PIX_FMT_YUV420:
192                 palette = VIDEO_PALETTE_YUV420;
193                 break;
194         case V4L2_PIX_FMT_YUV411P:
195                 palette = VIDEO_PALETTE_YUV411P;
196                 break;
197         case V4L2_PIX_FMT_YUV422P:
198                 palette = VIDEO_PALETTE_YUV422P;
199                 break;
200         }
201         return palette;
202 }
203
204 /* ----------------------------------------------------------------- */
205
206 static int poll_one(struct file *file)
207 {
208         int retval = 1;
209         poll_table *table;
210         struct poll_wqueues pwq;
211
212         poll_initwait(&pwq);
213         table = &pwq.pt;
214         for (;;) {
215                 int mask;
216                 set_current_state(TASK_INTERRUPTIBLE);
217                 mask = file->f_op->poll(file, table);
218                 if (mask & POLLIN)
219                         break;
220                 table = NULL;
221                 if (signal_pending(current)) {
222                         retval = -ERESTARTSYS;
223                         break;
224                 }
225                 schedule();
226         }
227         set_current_state(TASK_RUNNING);
228         poll_freewait(&pwq);
229         return retval;
230 }
231
232 static int count_inputs(struct inode         *inode,
233                         struct file          *file,
234                         v4l2_kioctl          drv)
235 {
236         struct v4l2_input input2;
237         int i;
238
239         for (i = 0;; i++) {
240                 memset(&input2,0,sizeof(input2));
241                 input2.index = i;
242                 if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
243                         break;
244         }
245         return i;
246 }
247
248 static int check_size(struct inode         *inode,
249                       struct file          *file,
250                       v4l2_kioctl          drv,
251                       int *maxw, int *maxh)
252 {
253         struct v4l2_fmtdesc desc2;
254         struct v4l2_format  fmt2;
255
256         memset(&desc2,0,sizeof(desc2));
257         memset(&fmt2,0,sizeof(fmt2));
258
259         desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
260         if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
261                 goto done;
262
263         fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
264         fmt2.fmt.pix.width       = 10000;
265         fmt2.fmt.pix.height      = 10000;
266         fmt2.fmt.pix.pixelformat = desc2.pixelformat;
267         if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
268                 goto done;
269
270         *maxw = fmt2.fmt.pix.width;
271         *maxh = fmt2.fmt.pix.height;
272
273  done:
274         return 0;
275 }
276
277 /* ----------------------------------------------------------------- */
278
279 /*
280  *      This function is exported.
281  */
282 int
283 v4l_compat_translate_ioctl(struct inode         *inode,
284                            struct file          *file,
285                            int                  cmd,
286                            void                 *arg,
287                            v4l2_kioctl          drv)
288 {
289         struct v4l2_capability  *cap2 = NULL;
290         struct v4l2_format      *fmt2 = NULL;
291         enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
292
293         struct v4l2_framebuffer fbuf2;
294         struct v4l2_input       input2;
295         struct v4l2_tuner       tun2;
296         struct v4l2_standard    std2;
297         struct v4l2_frequency   freq2;
298         struct v4l2_audio       aud2;
299         struct v4l2_queryctrl   qctrl2;
300         struct v4l2_buffer      buf2;
301         v4l2_std_id             sid;
302         int i, err = 0;
303
304         switch (cmd) {
305         case VIDIOCGCAP:        /* capability */
306         {
307                 struct video_capability *cap = arg;
308
309                 cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
310                 memset(cap, 0, sizeof(*cap));
311                 memset(cap2, 0, sizeof(*cap2));
312                 memset(&fbuf2, 0, sizeof(fbuf2));
313
314                 err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
315                 if (err < 0) {
316                         dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
317                         break;
318                 }
319                 if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
320                         err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
321                         if (err < 0) {
322                                 dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
323                                 memset(&fbuf2, 0, sizeof(fbuf2));
324                         }
325                         err = 0;
326                 }
327
328                 memcpy(cap->name, cap2->card,
329                        min(sizeof(cap->name), sizeof(cap2->card)));
330                 cap->name[sizeof(cap->name) - 1] = 0;
331                 if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
332                         cap->type |= VID_TYPE_CAPTURE;
333                 if (cap2->capabilities & V4L2_CAP_TUNER)
334                         cap->type |= VID_TYPE_TUNER;
335                 if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
336                         cap->type |= VID_TYPE_TELETEXT;
337                 if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
338                         cap->type |= VID_TYPE_OVERLAY;
339                 if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
340                         cap->type |= VID_TYPE_CLIPPING;
341
342                 cap->channels  = count_inputs(inode,file,drv);
343                 check_size(inode,file,drv,
344                            &cap->maxwidth,&cap->maxheight);
345                 cap->audios    =  0; /* FIXME */
346                 cap->minwidth  = 48; /* FIXME */
347                 cap->minheight = 32; /* FIXME */
348                 break;
349         }
350         case VIDIOCGFBUF: /*  get frame buffer  */
351         {
352                 struct video_buffer     *buffer = arg;
353
354                 err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
355                 if (err < 0) {
356                         dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
357                         break;
358                 }
359                 buffer->base   = fbuf2.base;
360                 buffer->height = fbuf2.fmt.height;
361                 buffer->width  = fbuf2.fmt.width;
362
363                 switch (fbuf2.fmt.pixelformat) {
364                 case V4L2_PIX_FMT_RGB332:
365                         buffer->depth = 8;
366                                 break;
367                 case V4L2_PIX_FMT_RGB555:
368                         buffer->depth = 15;
369                         break;
370                 case V4L2_PIX_FMT_RGB565:
371                         buffer->depth = 16;
372                         break;
373                 case V4L2_PIX_FMT_BGR24:
374                         buffer->depth = 24;
375                         break;
376                 case V4L2_PIX_FMT_BGR32:
377                         buffer->depth = 32;
378                         break;
379                 default:
380                         buffer->depth = 0;
381                 }
382                 if (0 != fbuf2.fmt.bytesperline)
383                         buffer->bytesperline = fbuf2.fmt.bytesperline;
384                 else {
385                         buffer->bytesperline =
386                                 (buffer->width * buffer->depth + 7) & 7;
387                         buffer->bytesperline >>= 3;
388                 }
389                 break;
390         }
391         case VIDIOCSFBUF: /*  set frame buffer  */
392         {
393                 struct video_buffer     *buffer = arg;
394
395                 memset(&fbuf2, 0, sizeof(fbuf2));
396                 fbuf2.base       = buffer->base;
397                 fbuf2.fmt.height = buffer->height;
398                 fbuf2.fmt.width  = buffer->width;
399                 switch (buffer->depth) {
400                 case 8:
401                         fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
402                         break;
403                 case 15:
404                         fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
405                         break;
406                 case 16:
407                         fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
408                         break;
409                 case 24:
410                         fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
411                         break;
412                 case 32:
413                         fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
414                         break;
415                 }
416                 fbuf2.fmt.bytesperline = buffer->bytesperline;
417                 err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
418                 if (err < 0)
419                         dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
420                 break;
421         }
422         case VIDIOCGWIN: /*  get window or capture dimensions  */
423         {
424                 struct video_window     *win = arg;
425
426                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
427                 memset(win,0,sizeof(*win));
428                 memset(fmt2,0,sizeof(*fmt2));
429
430                 fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
431                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
432                 if (err < 0)
433                         dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
434                 if (err == 0) {
435                         win->x         = fmt2->fmt.win.w.left;
436                         win->y         = fmt2->fmt.win.w.top;
437                         win->width     = fmt2->fmt.win.w.width;
438                         win->height    = fmt2->fmt.win.w.height;
439                         win->chromakey = fmt2->fmt.win.chromakey;
440                         win->clips     = NULL;
441                         win->clipcount = 0;
442                         break;
443                 }
444
445                 fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
446                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
447                 if (err < 0) {
448                         dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
449                         break;
450                 }
451                 win->x         = 0;
452                 win->y         = 0;
453                 win->width     = fmt2->fmt.pix.width;
454                 win->height    = fmt2->fmt.pix.height;
455                 win->chromakey = 0;
456                 win->clips     = NULL;
457                 win->clipcount = 0;
458                 break;
459         }
460         case VIDIOCSWIN: /*  set window and/or capture dimensions  */
461         {
462                 struct video_window     *win = arg;
463                 int err1,err2;
464
465                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
466                 memset(fmt2,0,sizeof(*fmt2));
467                 fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
468                 drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
469                 err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
470                 if (err1 < 0)
471                         dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
472                 if (err1 == 0) {
473                         fmt2->fmt.pix.width  = win->width;
474                         fmt2->fmt.pix.height = win->height;
475                         fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
476                         fmt2->fmt.pix.bytesperline = 0;
477                         err = drv(inode, file, VIDIOC_S_FMT, fmt2);
478                         if (err < 0)
479                                 dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
480                                         err);
481                         win->width  = fmt2->fmt.pix.width;
482                         win->height = fmt2->fmt.pix.height;
483                 }
484
485                 memset(fmt2,0,sizeof(*fmt2));
486                 fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
487                 fmt2->fmt.win.w.left    = win->x;
488                 fmt2->fmt.win.w.top     = win->y;
489                 fmt2->fmt.win.w.width   = win->width;
490                 fmt2->fmt.win.w.height  = win->height;
491                 fmt2->fmt.win.chromakey = win->chromakey;
492                 fmt2->fmt.win.clips     = (void __user *)win->clips;
493                 fmt2->fmt.win.clipcount = win->clipcount;
494                 err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
495                 if (err2 < 0)
496                         dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
497
498                 if (err1 != 0 && err2 != 0)
499                         err = err1;
500                 break;
501         }
502         case VIDIOCCAPTURE: /*  turn on/off preview  */
503         {
504                 int *on = arg;
505
506                 if (0 == *on) {
507                         /* dirty hack time.  But v4l1 has no STREAMOFF
508                          * equivalent in the API, and this one at
509                          * least comes close ... */
510                         drv(inode, file, VIDIOC_STREAMOFF, &captype);
511                 }
512                 err = drv(inode, file, VIDIOC_OVERLAY, arg);
513                 if (err < 0)
514                         dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
515                 break;
516         }
517         case VIDIOCGCHAN: /*  get input information  */
518         {
519                 struct video_channel    *chan = arg;
520
521                 memset(&input2,0,sizeof(input2));
522                 input2.index = chan->channel;
523                 err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
524                 if (err < 0) {
525                         dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
526                                 "channel=%d err=%d\n",chan->channel,err);
527                         break;
528                 }
529                 chan->channel = input2.index;
530                 memcpy(chan->name, input2.name,
531                        min(sizeof(chan->name), sizeof(input2.name)));
532                 chan->name[sizeof(chan->name) - 1] = 0;
533                 chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
534                 chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
535                 switch (input2.type) {
536                 case V4L2_INPUT_TYPE_TUNER:
537                         chan->type = VIDEO_TYPE_TV;
538                         break;
539                 default:
540                 case V4L2_INPUT_TYPE_CAMERA:
541                         chan->type = VIDEO_TYPE_CAMERA;
542                         break;
543                 }
544                 chan->norm = 0;
545                 err = drv(inode, file, VIDIOC_G_STD, &sid);
546                 if (err < 0)
547                         dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
548                 if (err == 0) {
549                         if (sid & V4L2_STD_PAL)
550                                 chan->norm = VIDEO_MODE_PAL;
551                         if (sid & V4L2_STD_NTSC)
552                                 chan->norm = VIDEO_MODE_NTSC;
553                         if (sid & V4L2_STD_SECAM)
554                                 chan->norm = VIDEO_MODE_SECAM;
555                 }
556                 break;
557         }
558         case VIDIOCSCHAN: /*  set input  */
559         {
560                 struct video_channel *chan = arg;
561
562                 sid = 0;
563                 err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
564                 if (err < 0)
565                         dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
566                 switch (chan->norm) {
567                 case VIDEO_MODE_PAL:
568                         sid = V4L2_STD_PAL;
569                         break;
570                 case VIDEO_MODE_NTSC:
571                         sid = V4L2_STD_NTSC;
572                         break;
573                 case VIDEO_MODE_SECAM:
574                         sid = V4L2_STD_SECAM;
575                         break;
576                 }
577                 if (0 != sid) {
578                         err = drv(inode, file, VIDIOC_S_STD, &sid);
579                         if (err < 0)
580                                 dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
581                 }
582                 break;
583         }
584         case VIDIOCGPICT: /*  get tone controls & partial capture format  */
585         {
586                 struct video_picture    *pict = arg;
587
588                 pict->brightness = get_v4l_control(inode, file,
589                                                    V4L2_CID_BRIGHTNESS,drv);
590                 pict->hue = get_v4l_control(inode, file,
591                                             V4L2_CID_HUE, drv);
592                 pict->contrast = get_v4l_control(inode, file,
593                                                  V4L2_CID_CONTRAST, drv);
594                 pict->colour = get_v4l_control(inode, file,
595                                                V4L2_CID_SATURATION, drv);
596                 pict->whiteness = get_v4l_control(inode, file,
597                                                   V4L2_CID_WHITENESS, drv);
598
599                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
600                 memset(fmt2,0,sizeof(*fmt2));
601                 fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
602                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
603                 if (err < 0) {
604                         dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
605                         break;
606                 }
607 #if 0 /* FIXME */
608                 pict->depth   = fmt2->fmt.pix.depth;
609 #endif
610                 pict->palette = pixelformat_to_palette(
611                         fmt2->fmt.pix.pixelformat);
612                 break;
613         }
614         case VIDIOCSPICT: /*  set tone controls & partial capture format  */
615         {
616                 struct video_picture    *pict = arg;
617
618                 set_v4l_control(inode, file,
619                                 V4L2_CID_BRIGHTNESS, pict->brightness, drv);
620                 set_v4l_control(inode, file,
621                                 V4L2_CID_HUE, pict->hue, drv);
622                 set_v4l_control(inode, file,
623                                 V4L2_CID_CONTRAST, pict->contrast, drv);
624                 set_v4l_control(inode, file,
625                                 V4L2_CID_SATURATION, pict->colour, drv);
626                 set_v4l_control(inode, file,
627                                 V4L2_CID_WHITENESS, pict->whiteness, drv);
628
629                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
630                 memset(fmt2,0,sizeof(*fmt2));
631                 fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
632                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
633                 if (err < 0)
634                         dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
635                 if (fmt2->fmt.pix.pixelformat !=
636                     palette_to_pixelformat(pict->palette)) {
637                         fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
638                                 pict->palette);
639                         err = drv(inode, file, VIDIOC_S_FMT, fmt2);
640                         if (err < 0)
641                                 dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
642                 }
643
644                 err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
645                 if (err < 0)
646                         dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
647                 if (fbuf2.fmt.pixelformat !=
648                     palette_to_pixelformat(pict->palette)) {
649                         fbuf2.fmt.pixelformat = palette_to_pixelformat(
650                                 pict->palette);
651                         err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
652                         if (err < 0)
653                                 dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
654                         err = 0; /* likely fails for non-root */
655                 }
656                 break;
657         }
658         case VIDIOCGTUNER: /*  get tuner information  */
659         {
660                 struct video_tuner      *tun = arg;
661
662                 memset(&tun2,0,sizeof(tun2));
663                 err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
664                 if (err < 0) {
665                         dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
666                         break;
667                 }
668                 memcpy(tun->name, tun2.name,
669                        min(sizeof(tun->name), sizeof(tun2.name)));
670                 tun->name[sizeof(tun->name) - 1] = 0;
671                 tun->rangelow = tun2.rangelow;
672                 tun->rangehigh = tun2.rangehigh;
673                 tun->flags = 0;
674                 tun->mode = VIDEO_MODE_AUTO;
675
676                 for (i = 0; i < 64; i++) {
677                         memset(&std2,0,sizeof(std2));
678                         std2.index = i;
679                         if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
680                                 break;
681                         if (std2.id & V4L2_STD_PAL)
682                                 tun->flags |= VIDEO_TUNER_PAL;
683                         if (std2.id & V4L2_STD_NTSC)
684                                 tun->flags |= VIDEO_TUNER_NTSC;
685                         if (std2.id & V4L2_STD_SECAM)
686                                 tun->flags |= VIDEO_TUNER_SECAM;
687                 }
688
689                 err = drv(inode, file, VIDIOC_G_STD, &sid);
690                 if (err < 0)
691                         dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
692                 if (err == 0) {
693                         if (sid & V4L2_STD_PAL)
694                                 tun->mode = VIDEO_MODE_PAL;
695                         if (sid & V4L2_STD_NTSC)
696                                 tun->mode = VIDEO_MODE_NTSC;
697                         if (sid & V4L2_STD_SECAM)
698                                 tun->mode = VIDEO_MODE_SECAM;
699                 }
700
701                 if (tun2.capability & V4L2_TUNER_CAP_LOW)
702                         tun->flags |= VIDEO_TUNER_LOW;
703                 if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
704                         tun->flags |= VIDEO_TUNER_STEREO_ON;
705                 tun->signal = tun2.signal;
706                 break;
707         }
708         case VIDIOCSTUNER: /*  select a tuner input  */
709         {
710 #if 0 /* FIXME */
711                 err = drv(inode, file, VIDIOC_S_INPUT, &i);
712                 if (err < 0)
713                         dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
714 #else
715                 err = 0;
716 #endif
717                 break;
718         }
719         case VIDIOCGFREQ: /*  get frequency  */
720         {
721                 int *freq = arg;
722
723                 freq2.tuner = 0;
724                 err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
725                 if (err < 0)
726                         dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
727                 if (0 == err)
728                         *freq = freq2.frequency;
729                 break;
730         }
731         case VIDIOCSFREQ: /*  set frequency  */
732         {
733                 int *freq = arg;
734
735                 freq2.tuner = 0;
736                 drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
737                 freq2.frequency = *freq;
738                 err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
739                 if (err < 0)
740                         dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
741                 break;
742         }
743         case VIDIOCGAUDIO: /*  get audio properties/controls  */
744         {
745                 struct video_audio      *aud = arg;
746
747                 err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
748                 if (err < 0) {
749                         dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
750                         break;
751                 }
752                 memcpy(aud->name, aud2.name,
753                        min(sizeof(aud->name), sizeof(aud2.name)));
754                 aud->name[sizeof(aud->name) - 1] = 0;
755                 aud->audio = aud2.index;
756                 aud->flags = 0;
757                 i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
758                 if (i >= 0) {
759                         aud->volume = i;
760                         aud->flags |= VIDEO_AUDIO_VOLUME;
761                 }
762                 i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
763                 if (i >= 0) {
764                         aud->bass = i;
765                         aud->flags |= VIDEO_AUDIO_BASS;
766                 }
767                 i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
768                 if (i >= 0) {
769                         aud->treble = i;
770                         aud->flags |= VIDEO_AUDIO_TREBLE;
771                 }
772                 i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
773                 if (i >= 0) {
774                         aud->balance = i;
775                         aud->flags |= VIDEO_AUDIO_BALANCE;
776                 }
777                 i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
778                 if (i >= 0) {
779                         if (i)
780                                 aud->flags |= VIDEO_AUDIO_MUTE;
781                         aud->flags |= VIDEO_AUDIO_MUTABLE;
782                 }
783                 aud->step = 1;
784                 qctrl2.id = V4L2_CID_AUDIO_VOLUME;
785                 if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
786                     !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
787                         aud->step = qctrl2.step;
788                 aud->mode = 0;
789
790                 memset(&tun2,0,sizeof(tun2));
791                 err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
792                 if (err < 0) {
793                         dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
794                         err = 0;
795                         break;
796                 }
797
798                 if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
799                         aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
800                 else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
801                         aud->mode = VIDEO_SOUND_STEREO;
802                 else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
803                         aud->mode = VIDEO_SOUND_MONO;
804                 break;
805         }
806         case VIDIOCSAUDIO: /*  set audio controls  */
807         {
808                 struct video_audio      *aud = arg;
809
810                 memset(&aud2,0,sizeof(aud2));
811                 memset(&tun2,0,sizeof(tun2));
812
813                 aud2.index = aud->audio;
814                 err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
815                 if (err < 0) {
816                         dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
817                         break;
818                 }
819
820                 set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
821                                 aud->volume, drv);
822                 set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
823                                 aud->bass, drv);
824                 set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
825                                 aud->treble, drv);
826                 set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
827                                 aud->balance, drv);
828                 set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
829                                 !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
830
831                 err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
832                 if (err < 0)
833                         dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
834                 if (err == 0) {
835                         switch (aud->mode) {
836                         default:
837                         case VIDEO_SOUND_MONO:
838                         case VIDEO_SOUND_LANG1:
839                                 tun2.audmode = V4L2_TUNER_MODE_MONO;
840                                 break;
841                         case VIDEO_SOUND_STEREO:
842                                 tun2.audmode = V4L2_TUNER_MODE_STEREO;
843                                 break;
844                         case VIDEO_SOUND_LANG2:
845                                 tun2.audmode = V4L2_TUNER_MODE_LANG2;
846                                 break;
847                         }
848                         err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
849                         if (err < 0)
850                                 dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
851                 }
852                 err = 0;
853                 break;
854         }
855 #if 0
856         case VIDIOCGMBUF:
857                 /* v4l2 drivers must implement that themself.  The
858                    mmap() differences can't be translated fully
859                    transparent, thus there is no point to try that */
860 #endif
861         case VIDIOCMCAPTURE: /*  capture a frame  */
862         {
863                 struct video_mmap       *mm = arg;
864
865                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
866                 memset(&buf2,0,sizeof(buf2));
867                 memset(fmt2,0,sizeof(*fmt2));
868
869                 fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
870                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
871                 if (err < 0) {
872                         dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
873                         break;
874                 }
875                 if (mm->width   != fmt2->fmt.pix.width  ||
876                     mm->height  != fmt2->fmt.pix.height ||
877                     palette_to_pixelformat(mm->format) !=
878                     fmt2->fmt.pix.pixelformat)
879                 {/* New capture format...  */
880                         fmt2->fmt.pix.width = mm->width;
881                         fmt2->fmt.pix.height = mm->height;
882                         fmt2->fmt.pix.pixelformat =
883                                 palette_to_pixelformat(mm->format);
884                         fmt2->fmt.pix.field = V4L2_FIELD_ANY;
885                         fmt2->fmt.pix.bytesperline = 0;
886                         err = drv(inode, file, VIDIOC_S_FMT, fmt2);
887                         if (err < 0) {
888                                 dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
889                                 break;
890                         }
891                 }
892                 buf2.index = mm->frame;
893                 buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
894                 err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
895                 if (err < 0) {
896                         dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
897                         break;
898                 }
899                 err = drv(inode, file, VIDIOC_QBUF, &buf2);
900                 if (err < 0) {
901                         dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
902                         break;
903                 }
904                 err = drv(inode, file, VIDIOC_STREAMON, &captype);
905                 if (err < 0)
906                         dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
907                 break;
908         }
909         case VIDIOCSYNC: /*  wait for a frame  */
910         {
911                 int                     *i = arg;
912
913                 buf2.index = *i;
914                 buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
915                 err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
916                 if (err < 0) {
917                         /*  No such buffer */
918                         dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
919                         break;
920                 }
921                 if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
922                         /* Buffer is not mapped  */
923                         err = -EINVAL;
924                         break;
925                 }
926
927                 /* make sure capture actually runs so we don't block forever */
928                 err = drv(inode, file, VIDIOC_STREAMON, &captype);
929                 if (err < 0) {
930                         dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
931                         break;
932                 }
933
934                 /*  Loop as long as the buffer is queued, but not done  */
935                 while ((buf2.flags &
936                         (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
937                        == V4L2_BUF_FLAG_QUEUED)
938                 {
939                         err = poll_one(file);
940                         if (err < 0 ||  /* error or sleep was interrupted  */
941                             err == 0)   /* timeout? Shouldn't occur.  */
942                                 break;
943                         err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
944                         if (err < 0)
945                                 dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
946                 }
947                 if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
948                         break;
949                 do {
950                         err = drv(inode, file, VIDIOC_DQBUF, &buf2);
951                         if (err < 0)
952                                 dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
953                 } while (err == 0 && buf2.index != *i);
954                 break;
955         }
956
957         case VIDIOCGVBIFMT: /* query VBI data capture format */
958         {
959                 struct vbi_format      *fmt = arg;
960
961                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
962                 memset(fmt2, 0, sizeof(*fmt2));
963                 fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
964
965                 err = drv(inode, file, VIDIOC_G_FMT, fmt2);
966                 if (err < 0) {
967                         dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
968                         break;
969                 }
970                 memset(fmt, 0, sizeof(*fmt));
971                 fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
972                 fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
973                 fmt->sample_format    = VIDEO_PALETTE_RAW;
974                 fmt->start[0]         = fmt2->fmt.vbi.start[0];
975                 fmt->count[0]         = fmt2->fmt.vbi.count[0];
976                 fmt->start[1]         = fmt2->fmt.vbi.start[1];
977                 fmt->count[1]         = fmt2->fmt.vbi.count[1];
978                 fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
979                 break;
980         }
981         case VIDIOCSVBIFMT:
982         {
983                 struct vbi_format      *fmt = arg;
984
985                 fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
986                 memset(fmt2, 0, sizeof(*fmt2));
987
988                 fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
989                 fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
990                 fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
991                 fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
992                 fmt2->fmt.vbi.start[0]         = fmt->start[0];
993                 fmt2->fmt.vbi.count[0]         = fmt->count[0];
994                 fmt2->fmt.vbi.start[1]         = fmt->start[1];
995                 fmt2->fmt.vbi.count[1]         = fmt->count[1];
996                 fmt2->fmt.vbi.flags            = fmt->flags;
997                 err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
998                 if (err < 0) {
999                         dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
1000                         break;
1001                 }
1002
1003                 if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
1004                     fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
1005                     VIDEO_PALETTE_RAW              != fmt->sample_format    ||
1006                     fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
1007                     fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
1008                     fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
1009                     fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
1010                     fmt2->fmt.vbi.flags            != fmt->flags) {
1011                         err = -EINVAL;
1012                         break;
1013                 }
1014                 err = drv(inode, file, VIDIOC_S_FMT, fmt2);
1015                 if (err < 0)
1016                         dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
1017                 break;
1018         }
1019
1020         default:
1021                 err = -ENOIOCTLCMD;
1022                 break;
1023         }
1024
1025         if (cap2)
1026                 kfree(cap2);
1027         if (fmt2)
1028                 kfree(fmt2);
1029         return err;
1030 }
1031
1032 EXPORT_SYMBOL(v4l_compat_translate_ioctl);
1033
1034 /*
1035  * Local variables:
1036  * c-basic-offset: 8
1037  * End:
1038  */