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