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