v4l1-compat.c 31.2 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13
 *	Video for Linux Two
 *	Backward Compatibility Layer
 *
 *	Support subroutines for providing V4L2 drivers with backward
 *	compatibility with applications using the old API.
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
14
 * Author:	Bill Dirks <bill@thedirks.org>
L
Linus Torvalds 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *		et al.
 *
 */


#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/videodev.h>
32
#include <media/v4l2-common.h>
33
#include <media/v4l2-ioctl.h>
L
Linus Torvalds 已提交
34 35 36 37 38

#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/pgtable.h>

39
static unsigned int debug;
L
Linus Torvalds 已提交
40
module_param(debug, int, 0644);
41
MODULE_PARM_DESC(debug, "enable debug messages");
L
Linus Torvalds 已提交
42 43 44 45
MODULE_AUTHOR("Bill Dirks");
MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
MODULE_LICENSE("GPL");

46 47 48 49 50
#define dprintk(fmt, arg...) \
	do { \
		if (debug) \
			printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg);\
	} while (0)
L
Linus Torvalds 已提交
51 52 53 54 55 56 57 58 59

/*
 *	I O C T L   T R A N S L A T I O N
 *
 *	From here on down is the code for translating the numerous
 *	ioctl commands from the old API to the new API.
 */

static int
60
get_v4l_control(struct file             *file,
L
Linus Torvalds 已提交
61 62 63 64 65 66 67 68
		int			cid,
		v4l2_kioctl             drv)
{
	struct v4l2_queryctrl	qctrl2;
	struct v4l2_control	ctrl2;
	int			err;

	qctrl2.id = cid;
69
	err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
L
Linus Torvalds 已提交
70
	if (err < 0)
71 72
		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
	if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) {
L
Linus Torvalds 已提交
73
		ctrl2.id = qctrl2.id;
74
		err = drv(file, VIDIOC_G_CTRL, &ctrl2);
L
Linus Torvalds 已提交
75
		if (err < 0) {
76
			dprintk("VIDIOC_G_CTRL: %d\n", err);
L
Linus Torvalds 已提交
77 78 79 80 81 82 83 84 85 86
			return 0;
		}
		return ((ctrl2.value - qctrl2.minimum) * 65535
			 + (qctrl2.maximum - qctrl2.minimum) / 2)
			/ (qctrl2.maximum - qctrl2.minimum);
	}
	return 0;
}

static int
87
set_v4l_control(struct file             *file,
L
Linus Torvalds 已提交
88 89 90 91 92 93 94 95 96
		int			cid,
		int			value,
		v4l2_kioctl             drv)
{
	struct v4l2_queryctrl	qctrl2;
	struct v4l2_control	ctrl2;
	int			err;

	qctrl2.id = cid;
97
	err = drv(file, VIDIOC_QUERYCTRL, &qctrl2);
L
Linus Torvalds 已提交
98
	if (err < 0)
99
		dprintk("VIDIOC_QUERYCTRL: %d\n", err);
L
Linus Torvalds 已提交
100 101
	if (err == 0 &&
	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
102
	    !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED)) {
L
Linus Torvalds 已提交
103 104 105 106 107 108 109 110 111 112 113 114
		if (value < 0)
			value = 0;
		if (value > 65535)
			value = 65535;
		if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
			value = 65535;
		ctrl2.id = qctrl2.id;
		ctrl2.value =
			(value * (qctrl2.maximum - qctrl2.minimum)
			 + 32767)
			/ 65535;
		ctrl2.value += qctrl2.minimum;
115
		err = drv(file, VIDIOC_S_CTRL, &ctrl2);
L
Linus Torvalds 已提交
116
		if (err < 0)
117
			dprintk("VIDIOC_S_CTRL: %d\n", err);
L
Linus Torvalds 已提交
118 119 120 121 122 123
	}
	return 0;
}

/* ----------------------------------------------------------------- */

124
static const unsigned int palette2pixelformat[] = {
L
Linus Torvalds 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
	[VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
	[VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
	[VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
	[VIDEO_PALETTE_RGB24]   = V4L2_PIX_FMT_BGR24,
	[VIDEO_PALETTE_RGB32]   = V4L2_PIX_FMT_BGR32,
	/* yuv packed pixel */
	[VIDEO_PALETTE_YUYV]    = V4L2_PIX_FMT_YUYV,
	[VIDEO_PALETTE_YUV422]  = V4L2_PIX_FMT_YUYV,
	[VIDEO_PALETTE_UYVY]    = V4L2_PIX_FMT_UYVY,
	/* yuv planar */
	[VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
	[VIDEO_PALETTE_YUV420]  = V4L2_PIX_FMT_YUV420,
	[VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
	[VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
	[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
};

142
static unsigned int __pure
L
Linus Torvalds 已提交
143 144 145 146 147 148 149 150
palette_to_pixelformat(unsigned int palette)
{
	if (palette < ARRAY_SIZE(palette2pixelformat))
		return palette2pixelformat[palette];
	else
		return 0;
}

151 152
static unsigned int __attribute_const__
pixelformat_to_palette(unsigned int pixelformat)
L
Linus Torvalds 已提交
153 154
{
	int	palette = 0;
155
	switch (pixelformat) {
L
Linus Torvalds 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	case V4L2_PIX_FMT_GREY:
		palette = VIDEO_PALETTE_GREY;
		break;
	case V4L2_PIX_FMT_RGB555:
		palette = VIDEO_PALETTE_RGB555;
		break;
	case V4L2_PIX_FMT_RGB565:
		palette = VIDEO_PALETTE_RGB565;
		break;
	case V4L2_PIX_FMT_BGR24:
		palette = VIDEO_PALETTE_RGB24;
		break;
	case V4L2_PIX_FMT_BGR32:
		palette = VIDEO_PALETTE_RGB32;
		break;
	/* yuv packed pixel */
	case V4L2_PIX_FMT_YUYV:
		palette = VIDEO_PALETTE_YUYV;
		break;
	case V4L2_PIX_FMT_UYVY:
		palette = VIDEO_PALETTE_UYVY;
		break;
	/* yuv planar */
	case V4L2_PIX_FMT_YUV410:
		palette = VIDEO_PALETTE_YUV420;
		break;
	case V4L2_PIX_FMT_YUV420:
		palette = VIDEO_PALETTE_YUV420;
		break;
	case V4L2_PIX_FMT_YUV411P:
		palette = VIDEO_PALETTE_YUV411P;
		break;
	case V4L2_PIX_FMT_YUV422P:
		palette = VIDEO_PALETTE_YUV422P;
		break;
	}
	return palette;
}

/* ----------------------------------------------------------------- */

197
static int poll_one(struct file *file, struct poll_wqueues *pwq)
L
Linus Torvalds 已提交
198 199 200 201
{
	int retval = 1;
	poll_table *table;

202 203
	poll_initwait(pwq);
	table = &pwq->pt;
L
Linus Torvalds 已提交
204 205 206 207 208 209 210 211 212 213
	for (;;) {
		int mask;
		mask = file->f_op->poll(file, table);
		if (mask & POLLIN)
			break;
		table = NULL;
		if (signal_pending(current)) {
			retval = -ERESTARTSYS;
			break;
		}
T
Tejun Heo 已提交
214
		poll_schedule(pwq, TASK_INTERRUPTIBLE);
L
Linus Torvalds 已提交
215
	}
216
	poll_freewait(pwq);
L
Linus Torvalds 已提交
217 218 219
	return retval;
}

220 221 222
static int count_inputs(
			struct file *file,
			v4l2_kioctl drv)
L
Linus Torvalds 已提交
223 224 225 226 227
{
	struct v4l2_input input2;
	int i;

	for (i = 0;; i++) {
228
		memset(&input2, 0, sizeof(input2));
L
Linus Torvalds 已提交
229
		input2.index = i;
230
		if (0 != drv(file, VIDIOC_ENUMINPUT, &input2))
L
Linus Torvalds 已提交
231 232 233 234 235
			break;
	}
	return i;
}

236 237 238 239 240
static int check_size(
		struct file *file,
		v4l2_kioctl drv,
		int *maxw,
		int *maxh)
L
Linus Torvalds 已提交
241 242 243 244
{
	struct v4l2_fmtdesc desc2;
	struct v4l2_format  fmt2;

245 246
	memset(&desc2, 0, sizeof(desc2));
	memset(&fmt2, 0, sizeof(fmt2));
L
Linus Torvalds 已提交
247 248

	desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
249
	if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2))
L
Linus Torvalds 已提交
250 251 252 253 254 255
		goto done;

	fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	fmt2.fmt.pix.width       = 10000;
	fmt2.fmt.pix.height      = 10000;
	fmt2.fmt.pix.pixelformat = desc2.pixelformat;
256
	if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2))
L
Linus Torvalds 已提交
257 258 259 260 261
		goto done;

	*maxw = fmt2.fmt.pix.width;
	*maxh = fmt2.fmt.pix.height;

262
done:
L
Linus Torvalds 已提交
263 264 265 266 267
	return 0;
}

/* ----------------------------------------------------------------- */

268
static noinline long v4l1_compat_get_capabilities(
269 270 271
					struct video_capability *cap,
					struct file *file,
					v4l2_kioctl drv)
L
Linus Torvalds 已提交
272
{
273
	long err;
274 275 276 277 278 279 280 281 282 283
	struct v4l2_framebuffer fbuf;
	struct v4l2_capability *cap2;

	cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
	if (!cap2) {
		err = -ENOMEM;
		return err;
	}
	memset(cap, 0, sizeof(*cap));
	memset(&fbuf, 0, sizeof(fbuf));
L
Linus Torvalds 已提交
284

285
	err = drv(file, VIDIOC_QUERYCAP, cap2);
286
	if (err < 0) {
287
		dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err);
288 289 290
		goto done;
	}
	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
291
		err = drv(file, VIDIOC_G_FBUF, &fbuf);
L
Linus Torvalds 已提交
292
		if (err < 0) {
293
			dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err);
294
			memset(&fbuf, 0, sizeof(fbuf));
L
Linus Torvalds 已提交
295
		}
296
		err = 0;
L
Linus Torvalds 已提交
297 298
	}

299 300 301 302 303 304 305 306 307 308 309 310 311 312
	memcpy(cap->name, cap2->card,
	       min(sizeof(cap->name), sizeof(cap2->card)));
	cap->name[sizeof(cap->name) - 1] = 0;
	if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
		cap->type |= VID_TYPE_CAPTURE;
	if (cap2->capabilities & V4L2_CAP_TUNER)
		cap->type |= VID_TYPE_TUNER;
	if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
		cap->type |= VID_TYPE_TELETEXT;
	if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
		cap->type |= VID_TYPE_OVERLAY;
	if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
		cap->type |= VID_TYPE_CLIPPING;

313 314
	cap->channels  = count_inputs(file, drv);
	check_size(file, drv,
315 316 317 318 319 320 321 322 323
		   &cap->maxwidth, &cap->maxheight);
	cap->audios    =  0; /* FIXME */
	cap->minwidth  = 48; /* FIXME */
	cap->minheight = 32; /* FIXME */

done:
	kfree(cap2);
	return err;
}
324

325
static noinline long v4l1_compat_get_frame_buffer(
326 327 328 329
					struct video_buffer *buffer,
					struct file *file,
					v4l2_kioctl drv)
{
330
	long err;
331
	struct v4l2_framebuffer fbuf;
L
Linus Torvalds 已提交
332

333 334 335
	memset(buffer, 0, sizeof(*buffer));
	memset(&fbuf, 0, sizeof(fbuf));

336
	err = drv(file, VIDIOC_G_FBUF, &fbuf);
337
	if (err < 0) {
338
		dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err);
339 340 341 342 343 344 345 346 347
		goto done;
	}
	buffer->base   = fbuf.base;
	buffer->height = fbuf.fmt.height;
	buffer->width  = fbuf.fmt.width;

	switch (fbuf.fmt.pixelformat) {
	case V4L2_PIX_FMT_RGB332:
		buffer->depth = 8;
L
Linus Torvalds 已提交
348
		break;
349 350 351 352 353 354 355 356 357 358 359 360 361 362
	case V4L2_PIX_FMT_RGB555:
		buffer->depth = 15;
		break;
	case V4L2_PIX_FMT_RGB565:
		buffer->depth = 16;
		break;
	case V4L2_PIX_FMT_BGR24:
		buffer->depth = 24;
		break;
	case V4L2_PIX_FMT_BGR32:
		buffer->depth = 32;
		break;
	default:
		buffer->depth = 0;
L
Linus Torvalds 已提交
363
	}
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
	if (fbuf.fmt.bytesperline) {
		buffer->bytesperline = fbuf.fmt.bytesperline;
		if (!buffer->depth && buffer->width)
			buffer->depth   = ((fbuf.fmt.bytesperline<<3)
					  + (buffer->width-1))
					  / buffer->width;
	} else {
		buffer->bytesperline =
			(buffer->width * buffer->depth + 7) & 7;
		buffer->bytesperline >>= 3;
	}
done:
	return err;
}

379
static noinline long v4l1_compat_set_frame_buffer(
380 381 382 383
					struct video_buffer *buffer,
					struct file *file,
					v4l2_kioctl drv)
{
384
	long err;
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
	struct v4l2_framebuffer fbuf;

	memset(&fbuf, 0, sizeof(fbuf));
	fbuf.base       = buffer->base;
	fbuf.fmt.height = buffer->height;
	fbuf.fmt.width  = buffer->width;
	switch (buffer->depth) {
	case 8:
		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
		break;
	case 15:
		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
		break;
	case 16:
		fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
		break;
	case 24:
		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
		break;
	case 32:
		fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
L
Linus Torvalds 已提交
406 407
		break;
	}
408
	fbuf.fmt.bytesperline = buffer->bytesperline;
409
	err = drv(file, VIDIOC_S_FBUF, &fbuf);
410
	if (err < 0)
411
		dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err);
412 413
	return err;
}
L
Linus Torvalds 已提交
414

415
static noinline long v4l1_compat_get_win_cap_dimensions(
416 417 418 419
					struct video_window *win,
					struct file *file,
					v4l2_kioctl drv)
{
420
	long err;
421
	struct v4l2_format *fmt;
L
Linus Torvalds 已提交
422

423 424 425 426 427 428
	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
	if (!fmt) {
		err = -ENOMEM;
		return err;
	}
	memset(win, 0, sizeof(*win));
L
Linus Torvalds 已提交
429

430
	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
431
	err = drv(file, VIDIOC_G_FMT, fmt);
432
	if (err < 0)
433
		dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err);
434 435 436 437 438 439
	if (err == 0) {
		win->x         = fmt->fmt.win.w.left;
		win->y         = fmt->fmt.win.w.top;
		win->width     = fmt->fmt.win.w.width;
		win->height    = fmt->fmt.win.w.height;
		win->chromakey = fmt->fmt.win.chromakey;
L
Linus Torvalds 已提交
440 441
		win->clips     = NULL;
		win->clipcount = 0;
442
		goto done;
L
Linus Torvalds 已提交
443 444
	}

445
	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
446
	err = drv(file, VIDIOC_G_FMT, fmt);
447
	if (err < 0) {
448
		dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err);
449 450 451 452 453 454 455 456 457 458 459 460 461
		goto done;
	}
	win->x         = 0;
	win->y         = 0;
	win->width     = fmt->fmt.pix.width;
	win->height    = fmt->fmt.pix.height;
	win->chromakey = 0;
	win->clips     = NULL;
	win->clipcount = 0;
done:
	kfree(fmt);
	return err;
}
L
Linus Torvalds 已提交
462

463
static noinline long v4l1_compat_set_win_cap_dimensions(
464 465 466 467
					struct video_window *win,
					struct file *file,
					v4l2_kioctl drv)
{
468
	long err, err1, err2;
469 470 471 472 473 474
	struct v4l2_format *fmt;

	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
	if (!fmt) {
		err = -ENOMEM;
		return err;
L
Linus Torvalds 已提交
475
	}
476
	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
477 478
	drv(file, VIDIOC_STREAMOFF, &fmt->type);
	err1 = drv(file, VIDIOC_G_FMT, fmt);
479
	if (err1 < 0)
480
		dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1);
481 482 483 484 485
	if (err1 == 0) {
		fmt->fmt.pix.width  = win->width;
		fmt->fmt.pix.height = win->height;
		fmt->fmt.pix.field  = V4L2_FIELD_ANY;
		fmt->fmt.pix.bytesperline = 0;
486
		err = drv(file, VIDIOC_S_FMT, fmt);
L
Linus Torvalds 已提交
487
		if (err < 0)
488
			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n",
489 490 491
				err);
		win->width  = fmt->fmt.pix.width;
		win->height = fmt->fmt.pix.height;
L
Linus Torvalds 已提交
492 493
	}

494 495 496 497 498 499 500 501 502
	memset(fmt, 0, sizeof(*fmt));
	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
	fmt->fmt.win.w.left    = win->x;
	fmt->fmt.win.w.top     = win->y;
	fmt->fmt.win.w.width   = win->width;
	fmt->fmt.win.w.height  = win->height;
	fmt->fmt.win.chromakey = win->chromakey;
	fmt->fmt.win.clips     = (void __user *)win->clips;
	fmt->fmt.win.clipcount = win->clipcount;
503
	err2 = drv(file, VIDIOC_S_FMT, fmt);
504
	if (err2 < 0)
505
		dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2);
506 507 508 509 510 511 512 513

	if (err1 != 0 && err2 != 0)
		err = err1;
	else
		err = 0;
	kfree(fmt);
	return err;
}
L
Linus Torvalds 已提交
514

515
static noinline long v4l1_compat_turn_preview_on_off(
516 517 518 519
					int *on,
					struct file *file,
					v4l2_kioctl drv)
{
520
	long err;
521 522 523 524 525 526
	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;

	if (0 == *on) {
		/* dirty hack time.  But v4l1 has no STREAMOFF
		 * equivalent in the API, and this one at
		 * least comes close ... */
527
		drv(file, VIDIOC_STREAMOFF, &captype);
L
Linus Torvalds 已提交
528
	}
529
	err = drv(file, VIDIOC_OVERLAY, on);
530
	if (err < 0)
531
		dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err);
532 533
	return err;
}
534

535
static noinline long v4l1_compat_get_input_info(
536 537 538 539
					struct video_channel *chan,
					struct file *file,
					v4l2_kioctl drv)
{
540
	long err;
541 542
	struct v4l2_input	input2;
	v4l2_std_id    		sid;
543

544 545
	memset(&input2, 0, sizeof(input2));
	input2.index = chan->channel;
546
	err = drv(file, VIDIOC_ENUMINPUT, &input2);
547 548
	if (err < 0) {
		dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
549
			"channel=%d err=%ld\n", chan->channel, err);
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
		goto done;
	}
	chan->channel = input2.index;
	memcpy(chan->name, input2.name,
	       min(sizeof(chan->name), sizeof(input2.name)));
	chan->name[sizeof(chan->name) - 1] = 0;
	chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
	chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
	switch (input2.type) {
	case V4L2_INPUT_TYPE_TUNER:
		chan->type = VIDEO_TYPE_TV;
		break;
	default:
	case V4L2_INPUT_TYPE_CAMERA:
		chan->type = VIDEO_TYPE_CAMERA;
L
Linus Torvalds 已提交
565 566
		break;
	}
567
	chan->norm = 0;
568
	err = drv(file, VIDIOC_G_STD, &sid);
569
	if (err < 0)
570
		dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err);
571 572 573 574 575 576 577 578 579 580 581
	if (err == 0) {
		if (sid & V4L2_STD_PAL)
			chan->norm = VIDEO_MODE_PAL;
		if (sid & V4L2_STD_NTSC)
			chan->norm = VIDEO_MODE_NTSC;
		if (sid & V4L2_STD_SECAM)
			chan->norm = VIDEO_MODE_SECAM;
	}
done:
	return err;
}
582

583
static noinline long v4l1_compat_set_input(
584 585 586 587
					struct video_channel *chan,
					struct file *file,
					v4l2_kioctl drv)
{
588
	long err;
589
	v4l2_std_id sid = 0;
L
Linus Torvalds 已提交
590

591
	err = drv(file, VIDIOC_S_INPUT, &chan->channel);
592
	if (err < 0)
593
		dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err);
594 595 596 597 598 599 600 601 602
	switch (chan->norm) {
	case VIDEO_MODE_PAL:
		sid = V4L2_STD_PAL;
		break;
	case VIDEO_MODE_NTSC:
		sid = V4L2_STD_NTSC;
		break;
	case VIDEO_MODE_SECAM:
		sid = V4L2_STD_SECAM;
L
Linus Torvalds 已提交
603 604
		break;
	}
605
	if (0 != sid) {
606
		err = drv(file, VIDIOC_S_STD, &sid);
L
Linus Torvalds 已提交
607
		if (err < 0)
608
			dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err);
L
Linus Torvalds 已提交
609
	}
610 611
	return err;
}
612

613
static noinline long v4l1_compat_get_picture(
614 615 616 617
					struct video_picture *pict,
					struct file *file,
					v4l2_kioctl drv)
{
618
	long err;
619
	struct v4l2_format *fmt;
620

621 622 623 624
	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
	if (!fmt) {
		err = -ENOMEM;
		return err;
L
Linus Torvalds 已提交
625 626
	}

627
	pict->brightness = get_v4l_control(file,
628
					   V4L2_CID_BRIGHTNESS, drv);
629
	pict->hue = get_v4l_control(file,
630
				    V4L2_CID_HUE, drv);
631
	pict->contrast = get_v4l_control(file,
632
					 V4L2_CID_CONTRAST, drv);
633
	pict->colour = get_v4l_control(file,
634
				       V4L2_CID_SATURATION, drv);
635
	pict->whiteness = get_v4l_control(file,
636 637 638
					  V4L2_CID_WHITENESS, drv);

	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
639
	err = drv(file, VIDIOC_G_FMT, fmt);
640
	if (err < 0) {
641
		dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err);
642
		goto done;
L
Linus Torvalds 已提交
643 644
	}

645 646 647 648 649 650 651 652 653 654
	pict->depth   = ((fmt->fmt.pix.bytesperline << 3)
			 + (fmt->fmt.pix.width - 1))
			 / fmt->fmt.pix.width;
	pict->palette = pixelformat_to_palette(
		fmt->fmt.pix.pixelformat);
done:
	kfree(fmt);
	return err;
}

655
static noinline long v4l1_compat_set_picture(
656 657 658 659
					struct video_picture *pict,
					struct file *file,
					v4l2_kioctl drv)
{
660
	long err;
661 662 663 664 665 666 667 668 669 670 671
	struct v4l2_framebuffer fbuf;
	int mem_err = 0, ovl_err = 0;
	struct v4l2_format *fmt;

	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
	if (!fmt) {
		err = -ENOMEM;
		return err;
	}
	memset(&fbuf, 0, sizeof(fbuf));

672
	set_v4l_control(file,
673
			V4L2_CID_BRIGHTNESS, pict->brightness, drv);
674
	set_v4l_control(file,
675
			V4L2_CID_HUE, pict->hue, drv);
676
	set_v4l_control(file,
677
			V4L2_CID_CONTRAST, pict->contrast, drv);
678
	set_v4l_control(file,
679
			V4L2_CID_SATURATION, pict->colour, drv);
680
	set_v4l_control(file,
681 682 683 684 685 686 687 688 689
			V4L2_CID_WHITENESS, pict->whiteness, drv);
	/*
	 * V4L1 uses this ioctl to set both memory capture and overlay
	 * pixel format, while V4L2 has two different ioctls for this.
	 * Some cards may not support one or the other, and may support
	 * different pixel formats for memory vs overlay.
	 */

	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
690
	err = drv(file, VIDIOC_G_FMT, fmt);
691 692 693 694
	/* If VIDIOC_G_FMT failed, then the driver likely doesn't
	   support memory capture.  Trying to set the memory capture
	   parameters would be pointless.  */
	if (err < 0) {
695
		dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err);
696 697 698 699 700
		mem_err = -1000;  /* didn't even try */
	} else if (fmt->fmt.pix.pixelformat !=
		 palette_to_pixelformat(pict->palette)) {
		fmt->fmt.pix.pixelformat = palette_to_pixelformat(
			pict->palette);
701
		mem_err = drv(file, VIDIOC_S_FMT, fmt);
702 703 704
		if (mem_err < 0)
			dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
				mem_err);
L
Linus Torvalds 已提交
705 706
	}

707
	err = drv(file, VIDIOC_G_FBUF, &fbuf);
708 709 710 711
	/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
	   support overlay.  Trying to set the overlay parameters
	   would be quite pointless.  */
	if (err < 0) {
712
		dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err);
713 714 715 716 717
		ovl_err = -1000;  /* didn't even try */
	} else if (fbuf.fmt.pixelformat !=
		 palette_to_pixelformat(pict->palette)) {
		fbuf.fmt.pixelformat = palette_to_pixelformat(
			pict->palette);
718
		ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf);
719 720 721 722 723 724 725 726 727
		if (ovl_err < 0)
			dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
				ovl_err);
	}
	if (ovl_err < 0 && mem_err < 0) {
		/* ioctl failed, couldn't set either parameter */
		if (mem_err != -1000)
			err = mem_err;
		else if (ovl_err == -EPERM)
L
Linus Torvalds 已提交
728
			err = 0;
729 730 731 732 733 734 735 736
		else
			err = ovl_err;
	} else
		err = 0;
	kfree(fmt);
	return err;
}

737
static noinline long v4l1_compat_get_tuner(
738 739 740 741
					struct video_tuner *tun,
					struct file *file,
					v4l2_kioctl drv)
{
742 743
	long err;
	int i;
744 745 746 747 748
	struct v4l2_tuner	tun2;
	struct v4l2_standard	std2;
	v4l2_std_id    		sid;

	memset(&tun2, 0, sizeof(tun2));
749
	err = drv(file, VIDIOC_G_TUNER, &tun2);
750
	if (err < 0) {
751
		dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err);
752 753 754 755 756 757 758 759 760 761 762 763 764
		goto done;
	}
	memcpy(tun->name, tun2.name,
	       min(sizeof(tun->name), sizeof(tun2.name)));
	tun->name[sizeof(tun->name) - 1] = 0;
	tun->rangelow = tun2.rangelow;
	tun->rangehigh = tun2.rangehigh;
	tun->flags = 0;
	tun->mode = VIDEO_MODE_AUTO;

	for (i = 0; i < 64; i++) {
		memset(&std2, 0, sizeof(std2));
		std2.index = i;
765
		if (0 != drv(file, VIDIOC_ENUMSTD, &std2))
L
Linus Torvalds 已提交
766
			break;
767 768 769 770 771 772 773
		if (std2.id & V4L2_STD_PAL)
			tun->flags |= VIDEO_TUNER_PAL;
		if (std2.id & V4L2_STD_NTSC)
			tun->flags |= VIDEO_TUNER_NTSC;
		if (std2.id & V4L2_STD_SECAM)
			tun->flags |= VIDEO_TUNER_SECAM;
	}
774

775
	err = drv(file, VIDIOC_G_STD, &sid);
776
	if (err < 0)
777
		dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err);
778 779 780 781 782 783 784
	if (err == 0) {
		if (sid & V4L2_STD_PAL)
			tun->mode = VIDEO_MODE_PAL;
		if (sid & V4L2_STD_NTSC)
			tun->mode = VIDEO_MODE_NTSC;
		if (sid & V4L2_STD_SECAM)
			tun->mode = VIDEO_MODE_SECAM;
L
Linus Torvalds 已提交
785 786
	}

787 788 789 790 791 792 793 794
	if (tun2.capability & V4L2_TUNER_CAP_LOW)
		tun->flags |= VIDEO_TUNER_LOW;
	if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
		tun->flags |= VIDEO_TUNER_STEREO_ON;
	tun->signal = tun2.signal;
done:
	return err;
}
L
Linus Torvalds 已提交
795

796
static noinline long v4l1_compat_select_tuner(
797 798 799 800
					struct video_tuner *tun,
					struct file *file,
					v4l2_kioctl drv)
{
801
	long err;
802 803
	struct v4l2_tuner	t;/*84 bytes on x86_64*/
	memset(&t, 0, sizeof(t));
L
Linus Torvalds 已提交
804

805 806
	t.index = tun->tuner;

807
	err = drv(file, VIDIOC_S_INPUT, &t);
808
	if (err < 0)
809
		dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %ld\n", err);
810 811 812
	return err;
}

813
static noinline long v4l1_compat_get_frequency(
814 815 816 817
					unsigned long *freq,
					struct file *file,
					v4l2_kioctl drv)
{
818
	long err;
819 820 821 822
	struct v4l2_frequency   freq2;
	memset(&freq2, 0, sizeof(freq2));

	freq2.tuner = 0;
823
	err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
824
	if (err < 0)
825
		dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err);
826 827 828 829 830
	if (0 == err)
		*freq = freq2.frequency;
	return err;
}

831
static noinline long v4l1_compat_set_frequency(
832 833 834 835
					unsigned long *freq,
					struct file *file,
					v4l2_kioctl drv)
{
836
	long err;
837 838 839
	struct v4l2_frequency   freq2;
	memset(&freq2, 0, sizeof(freq2));

840
	drv(file, VIDIOC_G_FREQUENCY, &freq2);
841
	freq2.frequency = *freq;
842
	err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
843
	if (err < 0)
844
		dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err);
845 846 847
	return err;
}

848
static noinline long v4l1_compat_get_audio(
849 850 851 852
					struct video_audio *aud,
					struct file *file,
					v4l2_kioctl drv)
{
853 854
	long err;
	int i;
855 856 857 858 859
	struct v4l2_queryctrl	qctrl2;
	struct v4l2_audio	aud2;
	struct v4l2_tuner	tun2;
	memset(&aud2, 0, sizeof(aud2));

860
	err = drv(file, VIDIOC_G_AUDIO, &aud2);
861
	if (err < 0) {
862
		dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err);
863 864 865 866 867 868 869
		goto done;
	}
	memcpy(aud->name, aud2.name,
	       min(sizeof(aud->name), sizeof(aud2.name)));
	aud->name[sizeof(aud->name) - 1] = 0;
	aud->audio = aud2.index;
	aud->flags = 0;
870
	i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv);
871 872 873 874
	if (i >= 0) {
		aud->volume = i;
		aud->flags |= VIDEO_AUDIO_VOLUME;
	}
875
	i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv);
876 877 878 879
	if (i >= 0) {
		aud->bass = i;
		aud->flags |= VIDEO_AUDIO_BASS;
	}
880
	i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv);
881 882 883 884
	if (i >= 0) {
		aud->treble = i;
		aud->flags |= VIDEO_AUDIO_TREBLE;
	}
885
	i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv);
886 887 888 889
	if (i >= 0) {
		aud->balance = i;
		aud->flags |= VIDEO_AUDIO_BALANCE;
	}
890
	i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv);
891 892 893 894 895 896 897
	if (i >= 0) {
		if (i)
			aud->flags |= VIDEO_AUDIO_MUTE;
		aud->flags |= VIDEO_AUDIO_MUTABLE;
	}
	aud->step = 1;
	qctrl2.id = V4L2_CID_AUDIO_VOLUME;
898
	if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
899 900 901 902 903
	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
		aud->step = qctrl2.step;
	aud->mode = 0;

	memset(&tun2, 0, sizeof(tun2));
904
	err = drv(file, VIDIOC_G_TUNER, &tun2);
905
	if (err < 0) {
906
		dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err);
L
Linus Torvalds 已提交
907
		err = 0;
908
		goto done;
L
Linus Torvalds 已提交
909 910
	}

911 912 913 914 915 916 917 918 919
	if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
		aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
	else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
		aud->mode = VIDEO_SOUND_STEREO;
	else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
		aud->mode = VIDEO_SOUND_MONO;
done:
	return err;
}
L
Linus Torvalds 已提交
920

921
static noinline long v4l1_compat_set_audio(
922 923 924 925
					struct video_audio *aud,
					struct file *file,
					v4l2_kioctl drv)
{
926
	long err;
927 928 929 930 931 932 933
	struct v4l2_audio	aud2;
	struct v4l2_tuner	tun2;

	memset(&aud2, 0, sizeof(aud2));
	memset(&tun2, 0, sizeof(tun2));

	aud2.index = aud->audio;
934
	err = drv(file, VIDIOC_S_AUDIO, &aud2);
935
	if (err < 0) {
936
		dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err);
937 938 939
		goto done;
	}

940
	set_v4l_control(file, V4L2_CID_AUDIO_VOLUME,
941
			aud->volume, drv);
942
	set_v4l_control(file, V4L2_CID_AUDIO_BASS,
943
			aud->bass, drv);
944
	set_v4l_control(file, V4L2_CID_AUDIO_TREBLE,
945
			aud->treble, drv);
946
	set_v4l_control(file, V4L2_CID_AUDIO_BALANCE,
947
			aud->balance, drv);
948
	set_v4l_control(file, V4L2_CID_AUDIO_MUTE,
949 950
			!!(aud->flags & VIDEO_AUDIO_MUTE), drv);

951
	err = drv(file, VIDIOC_G_TUNER, &tun2);
952
	if (err < 0)
953
		dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err);
954 955 956 957 958 959
	if (err == 0) {
		switch (aud->mode) {
		default:
		case VIDEO_SOUND_MONO:
		case VIDEO_SOUND_LANG1:
			tun2.audmode = V4L2_TUNER_MODE_MONO;
L
Linus Torvalds 已提交
960
			break;
961 962
		case VIDEO_SOUND_STEREO:
			tun2.audmode = V4L2_TUNER_MODE_STEREO;
L
Linus Torvalds 已提交
963
			break;
964 965
		case VIDEO_SOUND_LANG2:
			tun2.audmode = V4L2_TUNER_MODE_LANG2;
L
Linus Torvalds 已提交
966 967
			break;
		}
968
		err = drv(file, VIDIOC_S_TUNER, &tun2);
L
Linus Torvalds 已提交
969
		if (err < 0)
970
			dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err);
L
Linus Torvalds 已提交
971
	}
972 973 974 975
	err = 0;
done:
	return err;
}
L
Linus Torvalds 已提交
976

977
static noinline long v4l1_compat_capture_frame(
978 979 980 981
					struct video_mmap *mm,
					struct file *file,
					v4l2_kioctl drv)
{
982
	long err;
983 984 985
	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	struct v4l2_buffer	buf;
	struct v4l2_format	*fmt;
L
Linus Torvalds 已提交
986

987 988 989 990 991 992 993 994
	fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
	if (!fmt) {
		err = -ENOMEM;
		return err;
	}
	memset(&buf, 0, sizeof(buf));

	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
995
	err = drv(file, VIDIOC_G_FMT, fmt);
996
	if (err < 0) {
997
		dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err);
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
		goto done;
	}
	if (mm->width   != fmt->fmt.pix.width  ||
	    mm->height  != fmt->fmt.pix.height ||
	    palette_to_pixelformat(mm->format) !=
	    fmt->fmt.pix.pixelformat) {
		/* New capture format...  */
		fmt->fmt.pix.width = mm->width;
		fmt->fmt.pix.height = mm->height;
		fmt->fmt.pix.pixelformat =
			palette_to_pixelformat(mm->format);
		fmt->fmt.pix.field = V4L2_FIELD_ANY;
		fmt->fmt.pix.bytesperline = 0;
1011
		err = drv(file, VIDIOC_S_FMT, fmt);
L
Linus Torvalds 已提交
1012
		if (err < 0) {
1013
			dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err);
1014
			goto done;
L
Linus Torvalds 已提交
1015
		}
1016 1017 1018
	}
	buf.index = mm->frame;
	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019
	err = drv(file, VIDIOC_QUERYBUF, &buf);
1020
	if (err < 0) {
1021
		dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err);
1022 1023
		goto done;
	}
1024
	err = drv(file, VIDIOC_QBUF, &buf);
1025
	if (err < 0) {
1026
		dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err);
1027 1028
		goto done;
	}
1029
	err = drv(file, VIDIOC_STREAMON, &captype);
1030
	if (err < 0)
1031
		dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err);
1032 1033 1034 1035
done:
	kfree(fmt);
	return err;
}
L
Linus Torvalds 已提交
1036

1037
static noinline long v4l1_compat_sync(
1038 1039 1040 1041
				int *i,
				struct file *file,
				v4l2_kioctl drv)
{
1042
	long err;
1043 1044
	enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	struct v4l2_buffer buf;
1045
	struct poll_wqueues *pwq;
1046 1047 1048 1049

	memset(&buf, 0, sizeof(buf));
	buf.index = *i;
	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1050
	err = drv(file, VIDIOC_QUERYBUF, &buf);
1051 1052
	if (err < 0) {
		/*  No such buffer */
1053
		dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
1054 1055 1056 1057 1058 1059
		goto done;
	}
	if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
		/* Buffer is not mapped  */
		err = -EINVAL;
		goto done;
L
Linus Torvalds 已提交
1060 1061
	}

1062
	/* make sure capture actually runs so we don't block forever */
1063
	err = drv(file, VIDIOC_STREAMON, &captype);
1064
	if (err < 0) {
1065
		dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err);
1066 1067
		goto done;
	}
L
Linus Torvalds 已提交
1068

1069
	pwq = kmalloc(sizeof(*pwq), GFP_KERNEL);
1070 1071 1072
	/*  Loop as long as the buffer is queued, but not done  */
	while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
						== V4L2_BUF_FLAG_QUEUED) {
1073
		err = poll_one(file, pwq);
1074 1075
		if (err < 0 ||	/* error or sleep was interrupted  */
		    err == 0)	/* timeout? Shouldn't occur.  */
1076
			break;
1077
		err = drv(file, VIDIOC_QUERYBUF, &buf);
1078
		if (err < 0)
1079
			dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
1080
	}
1081
	kfree(pwq);
1082 1083 1084
	if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
		goto done;
	do {
1085
		err = drv(file, VIDIOC_DQBUF, &buf);
1086
		if (err < 0)
1087
			dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err);
1088 1089 1090 1091
	} while (err == 0 && buf.index != *i);
done:
	return err;
}
L
Linus Torvalds 已提交
1092

1093
static noinline long v4l1_compat_get_vbi_format(
1094 1095 1096 1097
				struct vbi_format *fmt,
				struct file *file,
				v4l2_kioctl drv)
{
1098
	long err;
1099 1100 1101 1102 1103 1104
	struct v4l2_format *fmt2;

	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
	if (!fmt2) {
		err = -ENOMEM;
		return err;
L
Linus Torvalds 已提交
1105
	}
1106
	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
L
Linus Torvalds 已提交
1107

1108
	err = drv(file, VIDIOC_G_FMT, fmt2);
1109
	if (err < 0) {
1110
		dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err);
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
		goto done;
	}
	if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
		err = -EINVAL;
		goto done;
	}
	memset(fmt, 0, sizeof(*fmt));
	fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
	fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
	fmt->sample_format    = VIDEO_PALETTE_RAW;
	fmt->start[0]         = fmt2->fmt.vbi.start[0];
	fmt->count[0]         = fmt2->fmt.vbi.count[0];
	fmt->start[1]         = fmt2->fmt.vbi.start[1];
	fmt->count[1]         = fmt2->fmt.vbi.count[1];
	fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
done:
	kfree(fmt2);
	return err;
}
1130

1131
static noinline long v4l1_compat_set_vbi_format(
1132 1133 1134 1135
				struct vbi_format *fmt,
				struct file *file,
				v4l2_kioctl drv)
{
1136
	long err;
1137
	struct v4l2_format	*fmt2 = NULL;
L
Linus Torvalds 已提交
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147
	if (VIDEO_PALETTE_RAW != fmt->sample_format) {
		err = -EINVAL;
		return err;
	}

	fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
	if (!fmt2) {
		err = -ENOMEM;
		return err;
L
Linus Torvalds 已提交
1148
	}
1149 1150 1151 1152 1153 1154 1155 1156 1157
	fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
	fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
	fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
	fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
	fmt2->fmt.vbi.start[0]         = fmt->start[0];
	fmt2->fmt.vbi.count[0]         = fmt->count[0];
	fmt2->fmt.vbi.start[1]         = fmt->start[1];
	fmt2->fmt.vbi.count[1]         = fmt->count[1];
	fmt2->fmt.vbi.flags            = fmt->flags;
1158
	err = drv(file, VIDIOC_TRY_FMT, fmt2);
1159
	if (err < 0) {
1160
		dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err);
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
		goto done;
	}

	if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
	    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
	    fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
	    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
	    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
	    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
	    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
	    fmt2->fmt.vbi.flags            != fmt->flags) {
		err = -EINVAL;
		goto done;
	}
1175
	err = drv(file, VIDIOC_S_FMT, fmt2);
1176
	if (err < 0)
1177
		dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err);
1178 1179 1180 1181 1182 1183 1184 1185
done:
	kfree(fmt2);
	return err;
}

/*
 *	This function is exported.
 */
1186
long
1187
v4l_compat_translate_ioctl(struct file		*file,
1188 1189 1190 1191
			   int			cmd,
			   void			*arg,
			   v4l2_kioctl          drv)
{
1192
	long err;
L
Linus Torvalds 已提交
1193

1194 1195
	switch (cmd) {
	case VIDIOCGCAP:	/* capability */
1196
		err = v4l1_compat_get_capabilities(arg, file, drv);
1197 1198
		break;
	case VIDIOCGFBUF: /*  get frame buffer  */
1199
		err = v4l1_compat_get_frame_buffer(arg, file, drv);
1200 1201
		break;
	case VIDIOCSFBUF: /*  set frame buffer  */
1202
		err = v4l1_compat_set_frame_buffer(arg, file, drv);
1203 1204
		break;
	case VIDIOCGWIN: /*  get window or capture dimensions  */
1205
		err = v4l1_compat_get_win_cap_dimensions(arg, file, drv);
1206 1207
		break;
	case VIDIOCSWIN: /*  set window and/or capture dimensions  */
1208
		err = v4l1_compat_set_win_cap_dimensions(arg, file, drv);
1209 1210
		break;
	case VIDIOCCAPTURE: /*  turn on/off preview  */
1211
		err = v4l1_compat_turn_preview_on_off(arg, file, drv);
1212 1213
		break;
	case VIDIOCGCHAN: /*  get input information  */
1214
		err = v4l1_compat_get_input_info(arg, file, drv);
1215 1216
		break;
	case VIDIOCSCHAN: /*  set input  */
1217
		err = v4l1_compat_set_input(arg, file, drv);
1218 1219
		break;
	case VIDIOCGPICT: /*  get tone controls & partial capture format  */
1220
		err = v4l1_compat_get_picture(arg, file, drv);
1221 1222
		break;
	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
1223
		err = v4l1_compat_set_picture(arg, file, drv);
1224 1225
		break;
	case VIDIOCGTUNER: /*  get tuner information  */
1226
		err = v4l1_compat_get_tuner(arg, file, drv);
1227 1228
		break;
	case VIDIOCSTUNER: /*  select a tuner input  */
1229
		err = v4l1_compat_select_tuner(arg, file, drv);
1230 1231
		break;
	case VIDIOCGFREQ: /*  get frequency  */
1232
		err = v4l1_compat_get_frequency(arg, file, drv);
1233 1234
		break;
	case VIDIOCSFREQ: /*  set frequency  */
1235
		err = v4l1_compat_set_frequency(arg, file, drv);
1236 1237
		break;
	case VIDIOCGAUDIO: /*  get audio properties/controls  */
1238
		err = v4l1_compat_get_audio(arg, file, drv);
1239 1240
		break;
	case VIDIOCSAUDIO: /*  set audio controls  */
1241
		err = v4l1_compat_set_audio(arg, file, drv);
1242 1243
		break;
	case VIDIOCMCAPTURE: /*  capture a frame  */
1244
		err = v4l1_compat_capture_frame(arg, file, drv);
1245 1246
		break;
	case VIDIOCSYNC: /*  wait for a frame  */
1247
		err = v4l1_compat_sync(arg, file, drv);
1248 1249
		break;
	case VIDIOCGVBIFMT: /* query VBI data capture format */
1250
		err = v4l1_compat_get_vbi_format(arg, file, drv);
1251 1252
		break;
	case VIDIOCSVBIFMT:
1253
		err = v4l1_compat_set_vbi_format(arg, file, drv);
1254
		break;
L
Linus Torvalds 已提交
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
	default:
		err = -ENOIOCTLCMD;
		break;
	}

	return err;
}
EXPORT_SYMBOL(v4l_compat_translate_ioctl);

/*
 * Local variables:
 * c-basic-offset: 8
 * End:
 */