diff options
author | Marcin Slusarz <marcin.slusarz@gmail.com> | 2008-04-22 13:45:57 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:07:50 -0400 |
commit | b524f7b02d70204444441e4805fb3a71981e9018 (patch) | |
tree | 5be09c3f6b5b2326761b2c73ea5f779bdc6a0b0f /drivers/media/video/v4l1-compat.c | |
parent | 8b3b90aca293418171297ae14efac5817ba02bd3 (diff) |
V4L/DVB (7364): reduce stack usage of v4l_compat_translate_ioctl
v4l_compat_translate_ioctl used 1376 bytes of stack (x86_64),
so split this 800 lines long function into ~20 small noinline functions;
the biggest function takes now 712 bytes (v4l1_compat_sync)
fix VIDIOCSWIN handler which printked wrong errors
Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/v4l1-compat.c')
-rw-r--r-- | drivers/media/video/v4l1-compat.c | 1681 |
1 files changed, 938 insertions, 743 deletions
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 6455b2f43bed..e42cea987964 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c | |||
@@ -203,7 +203,7 @@ static int poll_one(struct file *file) | |||
203 | { | 203 | { |
204 | int retval = 1; | 204 | int retval = 1; |
205 | poll_table *table; | 205 | poll_table *table; |
206 | struct poll_wqueues pwq; | 206 | struct poll_wqueues pwq; /*TODO: allocate dynamically*/ |
207 | 207 | ||
208 | poll_initwait(&pwq); | 208 | poll_initwait(&pwq); |
209 | table = &pwq.pt; | 209 | table = &pwq.pt; |
@@ -225,9 +225,10 @@ static int poll_one(struct file *file) | |||
225 | return retval; | 225 | return retval; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int count_inputs(struct inode *inode, | 228 | static int count_inputs( |
229 | struct file *file, | 229 | struct inode *inode, |
230 | v4l2_kioctl drv) | 230 | struct file *file, |
231 | v4l2_kioctl drv) | ||
231 | { | 232 | { |
232 | struct v4l2_input input2; | 233 | struct v4l2_input input2; |
233 | int i; | 234 | int i; |
@@ -241,10 +242,12 @@ static int count_inputs(struct inode *inode, | |||
241 | return i; | 242 | return i; |
242 | } | 243 | } |
243 | 244 | ||
244 | static int check_size(struct inode *inode, | 245 | static int check_size( |
245 | struct file *file, | 246 | struct inode *inode, |
246 | v4l2_kioctl drv, | 247 | struct file *file, |
247 | int *maxw, int *maxh) | 248 | v4l2_kioctl drv, |
249 | int *maxw, | ||
250 | int *maxh) | ||
248 | { | 251 | { |
249 | struct v4l2_fmtdesc desc2; | 252 | struct v4l2_fmtdesc desc2; |
250 | struct v4l2_format fmt2; | 253 | struct v4l2_format fmt2; |
@@ -266,828 +269,1020 @@ static int check_size(struct inode *inode, | |||
266 | *maxw = fmt2.fmt.pix.width; | 269 | *maxw = fmt2.fmt.pix.width; |
267 | *maxh = fmt2.fmt.pix.height; | 270 | *maxh = fmt2.fmt.pix.height; |
268 | 271 | ||
269 | done: | 272 | done: |
270 | return 0; | 273 | return 0; |
271 | } | 274 | } |
272 | 275 | ||
273 | /* ----------------------------------------------------------------- */ | 276 | /* ----------------------------------------------------------------- */ |
274 | 277 | ||
275 | /* | 278 | static noinline int v4l1_compat_get_capabilities( |
276 | * This function is exported. | 279 | struct video_capability *cap, |
277 | */ | 280 | struct inode *inode, |
278 | int | 281 | struct file *file, |
279 | v4l_compat_translate_ioctl(struct inode *inode, | 282 | v4l2_kioctl drv) |
280 | struct file *file, | ||
281 | int cmd, | ||
282 | void *arg, | ||
283 | v4l2_kioctl drv) | ||
284 | { | 283 | { |
285 | struct v4l2_capability *cap2 = NULL; | 284 | int err; |
286 | struct v4l2_format *fmt2 = NULL; | 285 | struct v4l2_framebuffer fbuf; |
287 | enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 286 | struct v4l2_capability *cap2; |
288 | 287 | ||
289 | struct v4l2_framebuffer fbuf2; | 288 | cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); |
290 | struct v4l2_input input2; | 289 | if (!cap2) { |
291 | struct v4l2_tuner tun2; | 290 | err = -ENOMEM; |
292 | struct v4l2_standard std2; | 291 | return err; |
293 | struct v4l2_frequency freq2; | 292 | } |
294 | struct v4l2_audio aud2; | 293 | memset(cap, 0, sizeof(*cap)); |
295 | struct v4l2_queryctrl qctrl2; | 294 | memset(&fbuf, 0, sizeof(fbuf)); |
296 | struct v4l2_buffer buf2; | ||
297 | v4l2_std_id sid; | ||
298 | int i, err = 0; | ||
299 | |||
300 | switch (cmd) { | ||
301 | case VIDIOCGCAP: /* capability */ | ||
302 | { | ||
303 | struct video_capability *cap = arg; | ||
304 | |||
305 | cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL); | ||
306 | if (!cap2) { | ||
307 | err = -ENOMEM; | ||
308 | break; | ||
309 | } | ||
310 | memset(cap, 0, sizeof(*cap)); | ||
311 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
312 | 295 | ||
313 | err = drv(inode, file, VIDIOC_QUERYCAP, cap2); | 296 | err = drv(inode, file, VIDIOC_QUERYCAP, cap2); |
297 | if (err < 0) { | ||
298 | dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); | ||
299 | goto done; | ||
300 | } | ||
301 | if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { | ||
302 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); | ||
314 | if (err < 0) { | 303 | if (err < 0) { |
315 | dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); | 304 | dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); |
316 | break; | 305 | memset(&fbuf, 0, sizeof(fbuf)); |
317 | } | ||
318 | if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { | ||
319 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | ||
320 | if (err < 0) { | ||
321 | dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); | ||
322 | memset(&fbuf2, 0, sizeof(fbuf2)); | ||
323 | } | ||
324 | err = 0; | ||
325 | } | 306 | } |
326 | 307 | err = 0; | |
327 | memcpy(cap->name, cap2->card, | ||
328 | min(sizeof(cap->name), sizeof(cap2->card))); | ||
329 | cap->name[sizeof(cap->name) - 1] = 0; | ||
330 | if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) | ||
331 | cap->type |= VID_TYPE_CAPTURE; | ||
332 | if (cap2->capabilities & V4L2_CAP_TUNER) | ||
333 | cap->type |= VID_TYPE_TUNER; | ||
334 | if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) | ||
335 | cap->type |= VID_TYPE_TELETEXT; | ||
336 | if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) | ||
337 | cap->type |= VID_TYPE_OVERLAY; | ||
338 | if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING) | ||
339 | cap->type |= VID_TYPE_CLIPPING; | ||
340 | |||
341 | cap->channels = count_inputs(inode, file, drv); | ||
342 | check_size(inode, file, drv, | ||
343 | &cap->maxwidth, &cap->maxheight); | ||
344 | cap->audios = 0; /* FIXME */ | ||
345 | cap->minwidth = 48; /* FIXME */ | ||
346 | cap->minheight = 32; /* FIXME */ | ||
347 | break; | ||
348 | } | 308 | } |
349 | case VIDIOCGFBUF: /* get frame buffer */ | ||
350 | { | ||
351 | struct video_buffer *buffer = arg; | ||
352 | 309 | ||
353 | memset(buffer, 0, sizeof(*buffer)); | 310 | memcpy(cap->name, cap2->card, |
354 | memset(&fbuf2, 0, sizeof(fbuf2)); | 311 | min(sizeof(cap->name), sizeof(cap2->card))); |
312 | cap->name[sizeof(cap->name) - 1] = 0; | ||
313 | if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) | ||
314 | cap->type |= VID_TYPE_CAPTURE; | ||
315 | if (cap2->capabilities & V4L2_CAP_TUNER) | ||
316 | cap->type |= VID_TYPE_TUNER; | ||
317 | if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) | ||
318 | cap->type |= VID_TYPE_TELETEXT; | ||
319 | if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) | ||
320 | cap->type |= VID_TYPE_OVERLAY; | ||
321 | if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING) | ||
322 | cap->type |= VID_TYPE_CLIPPING; | ||
323 | |||
324 | cap->channels = count_inputs(inode, file, drv); | ||
325 | check_size(inode, file, drv, | ||
326 | &cap->maxwidth, &cap->maxheight); | ||
327 | cap->audios = 0; /* FIXME */ | ||
328 | cap->minwidth = 48; /* FIXME */ | ||
329 | cap->minheight = 32; /* FIXME */ | ||
330 | |||
331 | done: | ||
332 | kfree(cap2); | ||
333 | return err; | ||
334 | } | ||
355 | 335 | ||
356 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | 336 | static noinline int v4l1_compat_get_frame_buffer( |
357 | if (err < 0) { | 337 | struct video_buffer *buffer, |
358 | dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); | 338 | struct inode *inode, |
359 | break; | 339 | struct file *file, |
360 | } | 340 | v4l2_kioctl drv) |
361 | buffer->base = fbuf2.base; | 341 | { |
362 | buffer->height = fbuf2.fmt.height; | 342 | int err; |
363 | buffer->width = fbuf2.fmt.width; | 343 | struct v4l2_framebuffer fbuf; |
364 | 344 | ||
365 | switch (fbuf2.fmt.pixelformat) { | 345 | memset(buffer, 0, sizeof(*buffer)); |
366 | case V4L2_PIX_FMT_RGB332: | 346 | memset(&fbuf, 0, sizeof(fbuf)); |
367 | buffer->depth = 8; | 347 | |
368 | break; | 348 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); |
369 | case V4L2_PIX_FMT_RGB555: | 349 | if (err < 0) { |
370 | buffer->depth = 15; | 350 | dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); |
371 | break; | 351 | goto done; |
372 | case V4L2_PIX_FMT_RGB565: | 352 | } |
373 | buffer->depth = 16; | 353 | buffer->base = fbuf.base; |
374 | break; | 354 | buffer->height = fbuf.fmt.height; |
375 | case V4L2_PIX_FMT_BGR24: | 355 | buffer->width = fbuf.fmt.width; |
376 | buffer->depth = 24; | 356 | |
377 | break; | 357 | switch (fbuf.fmt.pixelformat) { |
378 | case V4L2_PIX_FMT_BGR32: | 358 | case V4L2_PIX_FMT_RGB332: |
379 | buffer->depth = 32; | 359 | buffer->depth = 8; |
380 | break; | ||
381 | default: | ||
382 | buffer->depth = 0; | ||
383 | } | ||
384 | if (fbuf2.fmt.bytesperline) { | ||
385 | buffer->bytesperline = fbuf2.fmt.bytesperline; | ||
386 | if (!buffer->depth && buffer->width) | ||
387 | buffer->depth = ((fbuf2.fmt.bytesperline<<3) | ||
388 | + (buffer->width-1)) | ||
389 | / buffer->width; | ||
390 | } else { | ||
391 | buffer->bytesperline = | ||
392 | (buffer->width * buffer->depth + 7) & 7; | ||
393 | buffer->bytesperline >>= 3; | ||
394 | } | ||
395 | break; | 360 | break; |
361 | case V4L2_PIX_FMT_RGB555: | ||
362 | buffer->depth = 15; | ||
363 | break; | ||
364 | case V4L2_PIX_FMT_RGB565: | ||
365 | buffer->depth = 16; | ||
366 | break; | ||
367 | case V4L2_PIX_FMT_BGR24: | ||
368 | buffer->depth = 24; | ||
369 | break; | ||
370 | case V4L2_PIX_FMT_BGR32: | ||
371 | buffer->depth = 32; | ||
372 | break; | ||
373 | default: | ||
374 | buffer->depth = 0; | ||
396 | } | 375 | } |
397 | case VIDIOCSFBUF: /* set frame buffer */ | 376 | if (fbuf.fmt.bytesperline) { |
398 | { | 377 | buffer->bytesperline = fbuf.fmt.bytesperline; |
399 | struct video_buffer *buffer = arg; | 378 | if (!buffer->depth && buffer->width) |
400 | 379 | buffer->depth = ((fbuf.fmt.bytesperline<<3) | |
401 | memset(&fbuf2, 0, sizeof(fbuf2)); | 380 | + (buffer->width-1)) |
402 | fbuf2.base = buffer->base; | 381 | / buffer->width; |
403 | fbuf2.fmt.height = buffer->height; | 382 | } else { |
404 | fbuf2.fmt.width = buffer->width; | 383 | buffer->bytesperline = |
405 | switch (buffer->depth) { | 384 | (buffer->width * buffer->depth + 7) & 7; |
406 | case 8: | 385 | buffer->bytesperline >>= 3; |
407 | fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332; | 386 | } |
408 | break; | 387 | done: |
409 | case 15: | 388 | return err; |
410 | fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555; | 389 | } |
411 | break; | 390 | |
412 | case 16: | 391 | static noinline int v4l1_compat_set_frame_buffer( |
413 | fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565; | 392 | struct video_buffer *buffer, |
414 | break; | 393 | struct inode *inode, |
415 | case 24: | 394 | struct file *file, |
416 | fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24; | 395 | v4l2_kioctl drv) |
417 | break; | 396 | { |
418 | case 32: | 397 | int err; |
419 | fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32; | 398 | struct v4l2_framebuffer fbuf; |
420 | break; | 399 | |
421 | } | 400 | memset(&fbuf, 0, sizeof(fbuf)); |
422 | fbuf2.fmt.bytesperline = buffer->bytesperline; | 401 | fbuf.base = buffer->base; |
423 | err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); | 402 | fbuf.fmt.height = buffer->height; |
424 | if (err < 0) | 403 | fbuf.fmt.width = buffer->width; |
425 | dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); | 404 | switch (buffer->depth) { |
405 | case 8: | ||
406 | fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB332; | ||
407 | break; | ||
408 | case 15: | ||
409 | fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB555; | ||
410 | break; | ||
411 | case 16: | ||
412 | fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB565; | ||
413 | break; | ||
414 | case 24: | ||
415 | fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR24; | ||
416 | break; | ||
417 | case 32: | ||
418 | fbuf.fmt.pixelformat = V4L2_PIX_FMT_BGR32; | ||
426 | break; | 419 | break; |
427 | } | 420 | } |
428 | case VIDIOCGWIN: /* get window or capture dimensions */ | 421 | fbuf.fmt.bytesperline = buffer->bytesperline; |
429 | { | 422 | err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); |
430 | struct video_window *win = arg; | 423 | if (err < 0) |
424 | dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); | ||
425 | return err; | ||
426 | } | ||
431 | 427 | ||
432 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 428 | static noinline int v4l1_compat_get_win_cap_dimensions( |
433 | if (!fmt2) { | 429 | struct video_window *win, |
434 | err = -ENOMEM; | 430 | struct inode *inode, |
435 | break; | 431 | struct file *file, |
436 | } | 432 | v4l2_kioctl drv) |
437 | memset(win, 0, sizeof(*win)); | 433 | { |
434 | int err; | ||
435 | struct v4l2_format *fmt; | ||
438 | 436 | ||
439 | fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; | 437 | fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); |
440 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | 438 | if (!fmt) { |
441 | if (err < 0) | 439 | err = -ENOMEM; |
442 | dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); | 440 | return err; |
443 | if (err == 0) { | 441 | } |
444 | win->x = fmt2->fmt.win.w.left; | 442 | memset(win, 0, sizeof(*win)); |
445 | win->y = fmt2->fmt.win.w.top; | ||
446 | win->width = fmt2->fmt.win.w.width; | ||
447 | win->height = fmt2->fmt.win.w.height; | ||
448 | win->chromakey = fmt2->fmt.win.chromakey; | ||
449 | win->clips = NULL; | ||
450 | win->clipcount = 0; | ||
451 | break; | ||
452 | } | ||
453 | 443 | ||
454 | fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 444 | fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
455 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | 445 | err = drv(inode, file, VIDIOC_G_FMT, fmt); |
456 | if (err < 0) { | 446 | if (err < 0) |
457 | dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); | 447 | dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); |
458 | break; | 448 | if (err == 0) { |
459 | } | 449 | win->x = fmt->fmt.win.w.left; |
460 | win->x = 0; | 450 | win->y = fmt->fmt.win.w.top; |
461 | win->y = 0; | 451 | win->width = fmt->fmt.win.w.width; |
462 | win->width = fmt2->fmt.pix.width; | 452 | win->height = fmt->fmt.win.w.height; |
463 | win->height = fmt2->fmt.pix.height; | 453 | win->chromakey = fmt->fmt.win.chromakey; |
464 | win->chromakey = 0; | ||
465 | win->clips = NULL; | 454 | win->clips = NULL; |
466 | win->clipcount = 0; | 455 | win->clipcount = 0; |
467 | break; | 456 | goto done; |
468 | } | 457 | } |
469 | case VIDIOCSWIN: /* set window and/or capture dimensions */ | ||
470 | { | ||
471 | struct video_window *win = arg; | ||
472 | int err1, err2; | ||
473 | 458 | ||
474 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 459 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
475 | if (!fmt2) { | 460 | err = drv(inode, file, VIDIOC_G_FMT, fmt); |
476 | err = -ENOMEM; | 461 | if (err < 0) { |
477 | break; | 462 | dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); |
478 | } | 463 | goto done; |
479 | fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 464 | } |
480 | drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type); | 465 | win->x = 0; |
481 | err1 = drv(inode, file, VIDIOC_G_FMT, fmt2); | 466 | win->y = 0; |
482 | if (err1 < 0) | 467 | win->width = fmt->fmt.pix.width; |
483 | dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err); | 468 | win->height = fmt->fmt.pix.height; |
484 | if (err1 == 0) { | 469 | win->chromakey = 0; |
485 | fmt2->fmt.pix.width = win->width; | 470 | win->clips = NULL; |
486 | fmt2->fmt.pix.height = win->height; | 471 | win->clipcount = 0; |
487 | fmt2->fmt.pix.field = V4L2_FIELD_ANY; | 472 | done: |
488 | fmt2->fmt.pix.bytesperline = 0; | 473 | kfree(fmt); |
489 | err = drv(inode, file, VIDIOC_S_FMT, fmt2); | 474 | return err; |
490 | if (err < 0) | 475 | } |
491 | dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", | ||
492 | err); | ||
493 | win->width = fmt2->fmt.pix.width; | ||
494 | win->height = fmt2->fmt.pix.height; | ||
495 | } | ||
496 | 476 | ||
497 | memset(fmt2, 0, sizeof(*fmt2)); | 477 | static noinline int v4l1_compat_set_win_cap_dimensions( |
498 | fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; | 478 | struct video_window *win, |
499 | fmt2->fmt.win.w.left = win->x; | 479 | struct inode *inode, |
500 | fmt2->fmt.win.w.top = win->y; | 480 | struct file *file, |
501 | fmt2->fmt.win.w.width = win->width; | 481 | v4l2_kioctl drv) |
502 | fmt2->fmt.win.w.height = win->height; | 482 | { |
503 | fmt2->fmt.win.chromakey = win->chromakey; | 483 | int err, err1, err2; |
504 | fmt2->fmt.win.clips = (void __user *)win->clips; | 484 | struct v4l2_format *fmt; |
505 | fmt2->fmt.win.clipcount = win->clipcount; | 485 | |
506 | err2 = drv(inode, file, VIDIOC_S_FMT, fmt2); | 486 | fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); |
507 | if (err2 < 0) | 487 | if (!fmt) { |
508 | dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err); | 488 | err = -ENOMEM; |
509 | 489 | return err; | |
510 | if (err1 != 0 && err2 != 0) | ||
511 | err = err1; | ||
512 | break; | ||
513 | } | 490 | } |
514 | case VIDIOCCAPTURE: /* turn on/off preview */ | 491 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
515 | { | 492 | drv(inode, file, VIDIOC_STREAMOFF, &fmt->type); |
516 | int *on = arg; | 493 | err1 = drv(inode, file, VIDIOC_G_FMT, fmt); |
517 | 494 | if (err1 < 0) | |
518 | if (0 == *on) { | 495 | dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1); |
519 | /* dirty hack time. But v4l1 has no STREAMOFF | 496 | if (err1 == 0) { |
520 | * equivalent in the API, and this one at | 497 | fmt->fmt.pix.width = win->width; |
521 | * least comes close ... */ | 498 | fmt->fmt.pix.height = win->height; |
522 | drv(inode, file, VIDIOC_STREAMOFF, &captype); | 499 | fmt->fmt.pix.field = V4L2_FIELD_ANY; |
523 | } | 500 | fmt->fmt.pix.bytesperline = 0; |
524 | err = drv(inode, file, VIDIOC_OVERLAY, arg); | 501 | err = drv(inode, file, VIDIOC_S_FMT, fmt); |
525 | if (err < 0) | 502 | if (err < 0) |
526 | dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); | 503 | dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", |
527 | break; | 504 | err); |
505 | win->width = fmt->fmt.pix.width; | ||
506 | win->height = fmt->fmt.pix.height; | ||
528 | } | 507 | } |
529 | case VIDIOCGCHAN: /* get input information */ | ||
530 | { | ||
531 | struct video_channel *chan = arg; | ||
532 | 508 | ||
533 | memset(&input2, 0, sizeof(input2)); | 509 | memset(fmt, 0, sizeof(*fmt)); |
534 | input2.index = chan->channel; | 510 | fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
535 | err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); | 511 | fmt->fmt.win.w.left = win->x; |
536 | if (err < 0) { | 512 | fmt->fmt.win.w.top = win->y; |
537 | dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " | 513 | fmt->fmt.win.w.width = win->width; |
538 | "channel=%d err=%d\n", chan->channel, err); | 514 | fmt->fmt.win.w.height = win->height; |
539 | break; | 515 | fmt->fmt.win.chromakey = win->chromakey; |
540 | } | 516 | fmt->fmt.win.clips = (void __user *)win->clips; |
541 | chan->channel = input2.index; | 517 | fmt->fmt.win.clipcount = win->clipcount; |
542 | memcpy(chan->name, input2.name, | 518 | err2 = drv(inode, file, VIDIOC_S_FMT, fmt); |
543 | min(sizeof(chan->name), sizeof(input2.name))); | 519 | if (err2 < 0) |
544 | chan->name[sizeof(chan->name) - 1] = 0; | 520 | dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2); |
545 | chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; | 521 | |
546 | chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; | 522 | if (err1 != 0 && err2 != 0) |
547 | switch (input2.type) { | 523 | err = err1; |
548 | case V4L2_INPUT_TYPE_TUNER: | 524 | else |
549 | chan->type = VIDEO_TYPE_TV; | 525 | err = 0; |
550 | break; | 526 | kfree(fmt); |
551 | default: | 527 | return err; |
552 | case V4L2_INPUT_TYPE_CAMERA: | 528 | } |
553 | chan->type = VIDEO_TYPE_CAMERA; | ||
554 | break; | ||
555 | } | ||
556 | chan->norm = 0; | ||
557 | err = drv(inode, file, VIDIOC_G_STD, &sid); | ||
558 | if (err < 0) | ||
559 | dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); | ||
560 | if (err == 0) { | ||
561 | if (sid & V4L2_STD_PAL) | ||
562 | chan->norm = VIDEO_MODE_PAL; | ||
563 | if (sid & V4L2_STD_NTSC) | ||
564 | chan->norm = VIDEO_MODE_NTSC; | ||
565 | if (sid & V4L2_STD_SECAM) | ||
566 | chan->norm = VIDEO_MODE_SECAM; | ||
567 | } | ||
568 | break; | ||
569 | } | ||
570 | case VIDIOCSCHAN: /* set input */ | ||
571 | { | ||
572 | struct video_channel *chan = arg; | ||
573 | 529 | ||
574 | sid = 0; | 530 | static noinline int v4l1_compat_turn_preview_on_off( |
575 | err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); | 531 | int *on, |
576 | if (err < 0) | 532 | struct inode *inode, |
577 | dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); | 533 | struct file *file, |
578 | switch (chan->norm) { | 534 | v4l2_kioctl drv) |
579 | case VIDEO_MODE_PAL: | 535 | { |
580 | sid = V4L2_STD_PAL; | 536 | int err; |
581 | break; | 537 | enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
582 | case VIDEO_MODE_NTSC: | 538 | |
583 | sid = V4L2_STD_NTSC; | 539 | if (0 == *on) { |
584 | break; | 540 | /* dirty hack time. But v4l1 has no STREAMOFF |
585 | case VIDEO_MODE_SECAM: | 541 | * equivalent in the API, and this one at |
586 | sid = V4L2_STD_SECAM; | 542 | * least comes close ... */ |
587 | break; | 543 | drv(inode, file, VIDIOC_STREAMOFF, &captype); |
588 | } | ||
589 | if (0 != sid) { | ||
590 | err = drv(inode, file, VIDIOC_S_STD, &sid); | ||
591 | if (err < 0) | ||
592 | dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); | ||
593 | } | ||
594 | break; | ||
595 | } | 544 | } |
596 | case VIDIOCGPICT: /* get tone controls & partial capture format */ | 545 | err = drv(inode, file, VIDIOC_OVERLAY, on); |
597 | { | 546 | if (err < 0) |
598 | struct video_picture *pict = arg; | 547 | dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); |
599 | 548 | return err; | |
600 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 549 | } |
601 | if (!fmt2) { | ||
602 | err = -ENOMEM; | ||
603 | break; | ||
604 | } | ||
605 | 550 | ||
606 | pict->brightness = get_v4l_control(inode, file, | 551 | static noinline int v4l1_compat_get_input_info( |
607 | V4L2_CID_BRIGHTNESS, drv); | 552 | struct video_channel *chan, |
608 | pict->hue = get_v4l_control(inode, file, | 553 | struct inode *inode, |
609 | V4L2_CID_HUE, drv); | 554 | struct file *file, |
610 | pict->contrast = get_v4l_control(inode, file, | 555 | v4l2_kioctl drv) |
611 | V4L2_CID_CONTRAST, drv); | 556 | { |
612 | pict->colour = get_v4l_control(inode, file, | 557 | int err; |
613 | V4L2_CID_SATURATION, drv); | 558 | struct v4l2_input input2; |
614 | pict->whiteness = get_v4l_control(inode, file, | 559 | v4l2_std_id sid; |
615 | V4L2_CID_WHITENESS, drv); | ||
616 | |||
617 | fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
618 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | ||
619 | if (err < 0) { | ||
620 | dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); | ||
621 | break; | ||
622 | } | ||
623 | 560 | ||
624 | pict->depth = ((fmt2->fmt.pix.bytesperline << 3) | 561 | memset(&input2, 0, sizeof(input2)); |
625 | + (fmt2->fmt.pix.width - 1)) | 562 | input2.index = chan->channel; |
626 | / fmt2->fmt.pix.width; | 563 | err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); |
627 | pict->palette = pixelformat_to_palette( | 564 | if (err < 0) { |
628 | fmt2->fmt.pix.pixelformat); | 565 | dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " |
566 | "channel=%d err=%d\n", chan->channel, err); | ||
567 | goto done; | ||
568 | } | ||
569 | chan->channel = input2.index; | ||
570 | memcpy(chan->name, input2.name, | ||
571 | min(sizeof(chan->name), sizeof(input2.name))); | ||
572 | chan->name[sizeof(chan->name) - 1] = 0; | ||
573 | chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; | ||
574 | chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; | ||
575 | switch (input2.type) { | ||
576 | case V4L2_INPUT_TYPE_TUNER: | ||
577 | chan->type = VIDEO_TYPE_TV; | ||
578 | break; | ||
579 | default: | ||
580 | case V4L2_INPUT_TYPE_CAMERA: | ||
581 | chan->type = VIDEO_TYPE_CAMERA; | ||
629 | break; | 582 | break; |
630 | } | 583 | } |
631 | case VIDIOCSPICT: /* set tone controls & partial capture format */ | 584 | chan->norm = 0; |
632 | { | 585 | err = drv(inode, file, VIDIOC_G_STD, &sid); |
633 | struct video_picture *pict = arg; | 586 | if (err < 0) |
634 | int mem_err = 0, ovl_err = 0; | 587 | dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); |
588 | if (err == 0) { | ||
589 | if (sid & V4L2_STD_PAL) | ||
590 | chan->norm = VIDEO_MODE_PAL; | ||
591 | if (sid & V4L2_STD_NTSC) | ||
592 | chan->norm = VIDEO_MODE_NTSC; | ||
593 | if (sid & V4L2_STD_SECAM) | ||
594 | chan->norm = VIDEO_MODE_SECAM; | ||
595 | } | ||
596 | done: | ||
597 | return err; | ||
598 | } | ||
635 | 599 | ||
636 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 600 | static noinline int v4l1_compat_set_input( |
637 | if (!fmt2) { | 601 | struct video_channel *chan, |
638 | err = -ENOMEM; | 602 | struct inode *inode, |
639 | break; | 603 | struct file *file, |
640 | } | 604 | v4l2_kioctl drv) |
641 | memset(&fbuf2, 0, sizeof(fbuf2)); | 605 | { |
642 | 606 | int err; | |
643 | set_v4l_control(inode, file, | 607 | v4l2_std_id sid = 0; |
644 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); | ||
645 | set_v4l_control(inode, file, | ||
646 | V4L2_CID_HUE, pict->hue, drv); | ||
647 | set_v4l_control(inode, file, | ||
648 | V4L2_CID_CONTRAST, pict->contrast, drv); | ||
649 | set_v4l_control(inode, file, | ||
650 | V4L2_CID_SATURATION, pict->colour, drv); | ||
651 | set_v4l_control(inode, file, | ||
652 | V4L2_CID_WHITENESS, pict->whiteness, drv); | ||
653 | /* | ||
654 | * V4L1 uses this ioctl to set both memory capture and overlay | ||
655 | * pixel format, while V4L2 has two different ioctls for this. | ||
656 | * Some cards may not support one or the other, and may support | ||
657 | * different pixel formats for memory vs overlay. | ||
658 | */ | ||
659 | |||
660 | fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
661 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | ||
662 | /* If VIDIOC_G_FMT failed, then the driver likely doesn't | ||
663 | support memory capture. Trying to set the memory capture | ||
664 | parameters would be pointless. */ | ||
665 | if (err < 0) { | ||
666 | dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); | ||
667 | mem_err = -1000; /* didn't even try */ | ||
668 | } else if (fmt2->fmt.pix.pixelformat != | ||
669 | palette_to_pixelformat(pict->palette)) { | ||
670 | fmt2->fmt.pix.pixelformat = palette_to_pixelformat( | ||
671 | pict->palette); | ||
672 | mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2); | ||
673 | if (mem_err < 0) | ||
674 | dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", | ||
675 | mem_err); | ||
676 | } | ||
677 | 608 | ||
678 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); | 609 | err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); |
679 | /* If VIDIOC_G_FBUF failed, then the driver likely doesn't | 610 | if (err < 0) |
680 | support overlay. Trying to set the overlay parameters | 611 | dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); |
681 | would be quite pointless. */ | 612 | switch (chan->norm) { |
682 | if (err < 0) { | 613 | case VIDEO_MODE_PAL: |
683 | dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); | 614 | sid = V4L2_STD_PAL; |
684 | ovl_err = -1000; /* didn't even try */ | 615 | break; |
685 | } else if (fbuf2.fmt.pixelformat != | 616 | case VIDEO_MODE_NTSC: |
686 | palette_to_pixelformat(pict->palette)) { | 617 | sid = V4L2_STD_NTSC; |
687 | fbuf2.fmt.pixelformat = palette_to_pixelformat( | 618 | break; |
688 | pict->palette); | 619 | case VIDEO_MODE_SECAM: |
689 | ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); | 620 | sid = V4L2_STD_SECAM; |
690 | if (ovl_err < 0) | ||
691 | dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", | ||
692 | ovl_err); | ||
693 | } | ||
694 | if (ovl_err < 0 && mem_err < 0) { | ||
695 | /* ioctl failed, couldn't set either parameter */ | ||
696 | if (mem_err != -1000) | ||
697 | err = mem_err; | ||
698 | else if (ovl_err == -EPERM) | ||
699 | err = 0; | ||
700 | else | ||
701 | err = ovl_err; | ||
702 | } else | ||
703 | err = 0; | ||
704 | break; | 621 | break; |
705 | } | 622 | } |
706 | case VIDIOCGTUNER: /* get tuner information */ | 623 | if (0 != sid) { |
707 | { | 624 | err = drv(inode, file, VIDIOC_S_STD, &sid); |
708 | struct video_tuner *tun = arg; | ||
709 | |||
710 | memset(&tun2, 0, sizeof(tun2)); | ||
711 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | ||
712 | if (err < 0) { | ||
713 | dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); | ||
714 | break; | ||
715 | } | ||
716 | memcpy(tun->name, tun2.name, | ||
717 | min(sizeof(tun->name), sizeof(tun2.name))); | ||
718 | tun->name[sizeof(tun->name) - 1] = 0; | ||
719 | tun->rangelow = tun2.rangelow; | ||
720 | tun->rangehigh = tun2.rangehigh; | ||
721 | tun->flags = 0; | ||
722 | tun->mode = VIDEO_MODE_AUTO; | ||
723 | |||
724 | for (i = 0; i < 64; i++) { | ||
725 | memset(&std2, 0, sizeof(std2)); | ||
726 | std2.index = i; | ||
727 | if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) | ||
728 | break; | ||
729 | if (std2.id & V4L2_STD_PAL) | ||
730 | tun->flags |= VIDEO_TUNER_PAL; | ||
731 | if (std2.id & V4L2_STD_NTSC) | ||
732 | tun->flags |= VIDEO_TUNER_NTSC; | ||
733 | if (std2.id & V4L2_STD_SECAM) | ||
734 | tun->flags |= VIDEO_TUNER_SECAM; | ||
735 | } | ||
736 | |||
737 | err = drv(inode, file, VIDIOC_G_STD, &sid); | ||
738 | if (err < 0) | 625 | if (err < 0) |
739 | dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); | 626 | dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); |
740 | if (err == 0) { | ||
741 | if (sid & V4L2_STD_PAL) | ||
742 | tun->mode = VIDEO_MODE_PAL; | ||
743 | if (sid & V4L2_STD_NTSC) | ||
744 | tun->mode = VIDEO_MODE_NTSC; | ||
745 | if (sid & V4L2_STD_SECAM) | ||
746 | tun->mode = VIDEO_MODE_SECAM; | ||
747 | } | ||
748 | |||
749 | if (tun2.capability & V4L2_TUNER_CAP_LOW) | ||
750 | tun->flags |= VIDEO_TUNER_LOW; | ||
751 | if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) | ||
752 | tun->flags |= VIDEO_TUNER_STEREO_ON; | ||
753 | tun->signal = tun2.signal; | ||
754 | break; | ||
755 | } | 627 | } |
756 | case VIDIOCSTUNER: /* select a tuner input */ | 628 | return err; |
757 | { | 629 | } |
758 | struct video_tuner *tun = arg; | ||
759 | struct v4l2_tuner t; | ||
760 | memset(&t, 0, sizeof(t)); | ||
761 | |||
762 | t.index = tun->tuner; | ||
763 | 630 | ||
764 | err = drv(inode, file, VIDIOC_S_INPUT, &t); | 631 | static noinline int v4l1_compat_get_picture( |
765 | if (err < 0) | 632 | struct video_picture *pict, |
766 | dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); | 633 | struct inode *inode, |
634 | struct file *file, | ||
635 | v4l2_kioctl drv) | ||
636 | { | ||
637 | int err; | ||
638 | struct v4l2_format *fmt; | ||
767 | 639 | ||
768 | break; | 640 | fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); |
641 | if (!fmt) { | ||
642 | err = -ENOMEM; | ||
643 | return err; | ||
769 | } | 644 | } |
770 | case VIDIOCGFREQ: /* get frequency */ | ||
771 | { | ||
772 | unsigned long *freq = arg; | ||
773 | memset(&freq2, 0, sizeof(freq2)); | ||
774 | 645 | ||
775 | freq2.tuner = 0; | 646 | pict->brightness = get_v4l_control(inode, file, |
776 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 647 | V4L2_CID_BRIGHTNESS, drv); |
777 | if (err < 0) | 648 | pict->hue = get_v4l_control(inode, file, |
778 | dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); | 649 | V4L2_CID_HUE, drv); |
779 | if (0 == err) | 650 | pict->contrast = get_v4l_control(inode, file, |
780 | *freq = freq2.frequency; | 651 | V4L2_CID_CONTRAST, drv); |
781 | break; | 652 | pict->colour = get_v4l_control(inode, file, |
653 | V4L2_CID_SATURATION, drv); | ||
654 | pict->whiteness = get_v4l_control(inode, file, | ||
655 | V4L2_CID_WHITENESS, drv); | ||
656 | |||
657 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
658 | err = drv(inode, file, VIDIOC_G_FMT, fmt); | ||
659 | if (err < 0) { | ||
660 | dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); | ||
661 | goto done; | ||
782 | } | 662 | } |
783 | case VIDIOCSFREQ: /* set frequency */ | ||
784 | { | ||
785 | unsigned long *freq = arg; | ||
786 | memset(&freq2, 0, sizeof(freq2)); | ||
787 | 663 | ||
788 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | 664 | pict->depth = ((fmt->fmt.pix.bytesperline << 3) |
789 | freq2.frequency = *freq; | 665 | + (fmt->fmt.pix.width - 1)) |
790 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); | 666 | / fmt->fmt.pix.width; |
791 | if (err < 0) | 667 | pict->palette = pixelformat_to_palette( |
792 | dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); | 668 | fmt->fmt.pix.pixelformat); |
793 | break; | 669 | done: |
670 | kfree(fmt); | ||
671 | return err; | ||
672 | } | ||
673 | |||
674 | static noinline int v4l1_compat_set_picture( | ||
675 | struct video_picture *pict, | ||
676 | struct inode *inode, | ||
677 | struct file *file, | ||
678 | v4l2_kioctl drv) | ||
679 | { | ||
680 | int err; | ||
681 | struct v4l2_framebuffer fbuf; | ||
682 | int mem_err = 0, ovl_err = 0; | ||
683 | struct v4l2_format *fmt; | ||
684 | |||
685 | fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); | ||
686 | if (!fmt) { | ||
687 | err = -ENOMEM; | ||
688 | return err; | ||
689 | } | ||
690 | memset(&fbuf, 0, sizeof(fbuf)); | ||
691 | |||
692 | set_v4l_control(inode, file, | ||
693 | V4L2_CID_BRIGHTNESS, pict->brightness, drv); | ||
694 | set_v4l_control(inode, file, | ||
695 | V4L2_CID_HUE, pict->hue, drv); | ||
696 | set_v4l_control(inode, file, | ||
697 | V4L2_CID_CONTRAST, pict->contrast, drv); | ||
698 | set_v4l_control(inode, file, | ||
699 | V4L2_CID_SATURATION, pict->colour, drv); | ||
700 | set_v4l_control(inode, file, | ||
701 | V4L2_CID_WHITENESS, pict->whiteness, drv); | ||
702 | /* | ||
703 | * V4L1 uses this ioctl to set both memory capture and overlay | ||
704 | * pixel format, while V4L2 has two different ioctls for this. | ||
705 | * Some cards may not support one or the other, and may support | ||
706 | * different pixel formats for memory vs overlay. | ||
707 | */ | ||
708 | |||
709 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
710 | err = drv(inode, file, VIDIOC_G_FMT, fmt); | ||
711 | /* If VIDIOC_G_FMT failed, then the driver likely doesn't | ||
712 | support memory capture. Trying to set the memory capture | ||
713 | parameters would be pointless. */ | ||
714 | if (err < 0) { | ||
715 | dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err); | ||
716 | mem_err = -1000; /* didn't even try */ | ||
717 | } else if (fmt->fmt.pix.pixelformat != | ||
718 | palette_to_pixelformat(pict->palette)) { | ||
719 | fmt->fmt.pix.pixelformat = palette_to_pixelformat( | ||
720 | pict->palette); | ||
721 | mem_err = drv(inode, file, VIDIOC_S_FMT, fmt); | ||
722 | if (mem_err < 0) | ||
723 | dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", | ||
724 | mem_err); | ||
794 | } | 725 | } |
795 | case VIDIOCGAUDIO: /* get audio properties/controls */ | ||
796 | { | ||
797 | struct video_audio *aud = arg; | ||
798 | memset(&aud2, 0, sizeof(aud2)); | ||
799 | 726 | ||
800 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); | 727 | err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); |
801 | if (err < 0) { | 728 | /* If VIDIOC_G_FBUF failed, then the driver likely doesn't |
802 | dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); | 729 | support overlay. Trying to set the overlay parameters |
803 | break; | 730 | would be quite pointless. */ |
804 | } | 731 | if (err < 0) { |
805 | memcpy(aud->name, aud2.name, | 732 | dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err); |
806 | min(sizeof(aud->name), sizeof(aud2.name))); | 733 | ovl_err = -1000; /* didn't even try */ |
807 | aud->name[sizeof(aud->name) - 1] = 0; | 734 | } else if (fbuf.fmt.pixelformat != |
808 | aud->audio = aud2.index; | 735 | palette_to_pixelformat(pict->palette)) { |
809 | aud->flags = 0; | 736 | fbuf.fmt.pixelformat = palette_to_pixelformat( |
810 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); | 737 | pict->palette); |
811 | if (i >= 0) { | 738 | ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); |
812 | aud->volume = i; | 739 | if (ovl_err < 0) |
813 | aud->flags |= VIDEO_AUDIO_VOLUME; | 740 | dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", |
814 | } | 741 | ovl_err); |
815 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); | 742 | } |
816 | if (i >= 0) { | 743 | if (ovl_err < 0 && mem_err < 0) { |
817 | aud->bass = i; | 744 | /* ioctl failed, couldn't set either parameter */ |
818 | aud->flags |= VIDEO_AUDIO_BASS; | 745 | if (mem_err != -1000) |
819 | } | 746 | err = mem_err; |
820 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); | 747 | else if (ovl_err == -EPERM) |
821 | if (i >= 0) { | ||
822 | aud->treble = i; | ||
823 | aud->flags |= VIDEO_AUDIO_TREBLE; | ||
824 | } | ||
825 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); | ||
826 | if (i >= 0) { | ||
827 | aud->balance = i; | ||
828 | aud->flags |= VIDEO_AUDIO_BALANCE; | ||
829 | } | ||
830 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); | ||
831 | if (i >= 0) { | ||
832 | if (i) | ||
833 | aud->flags |= VIDEO_AUDIO_MUTE; | ||
834 | aud->flags |= VIDEO_AUDIO_MUTABLE; | ||
835 | } | ||
836 | aud->step = 1; | ||
837 | qctrl2.id = V4L2_CID_AUDIO_VOLUME; | ||
838 | if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && | ||
839 | !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) | ||
840 | aud->step = qctrl2.step; | ||
841 | aud->mode = 0; | ||
842 | |||
843 | memset(&tun2, 0, sizeof(tun2)); | ||
844 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | ||
845 | if (err < 0) { | ||
846 | dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); | ||
847 | err = 0; | 748 | err = 0; |
749 | else | ||
750 | err = ovl_err; | ||
751 | } else | ||
752 | err = 0; | ||
753 | kfree(fmt); | ||
754 | return err; | ||
755 | } | ||
756 | |||
757 | static noinline int v4l1_compat_get_tuner( | ||
758 | struct video_tuner *tun, | ||
759 | struct inode *inode, | ||
760 | struct file *file, | ||
761 | v4l2_kioctl drv) | ||
762 | { | ||
763 | int err, i; | ||
764 | struct v4l2_tuner tun2; | ||
765 | struct v4l2_standard std2; | ||
766 | v4l2_std_id sid; | ||
767 | |||
768 | memset(&tun2, 0, sizeof(tun2)); | ||
769 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | ||
770 | if (err < 0) { | ||
771 | dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); | ||
772 | goto done; | ||
773 | } | ||
774 | memcpy(tun->name, tun2.name, | ||
775 | min(sizeof(tun->name), sizeof(tun2.name))); | ||
776 | tun->name[sizeof(tun->name) - 1] = 0; | ||
777 | tun->rangelow = tun2.rangelow; | ||
778 | tun->rangehigh = tun2.rangehigh; | ||
779 | tun->flags = 0; | ||
780 | tun->mode = VIDEO_MODE_AUTO; | ||
781 | |||
782 | for (i = 0; i < 64; i++) { | ||
783 | memset(&std2, 0, sizeof(std2)); | ||
784 | std2.index = i; | ||
785 | if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) | ||
848 | break; | 786 | break; |
849 | } | 787 | if (std2.id & V4L2_STD_PAL) |
788 | tun->flags |= VIDEO_TUNER_PAL; | ||
789 | if (std2.id & V4L2_STD_NTSC) | ||
790 | tun->flags |= VIDEO_TUNER_NTSC; | ||
791 | if (std2.id & V4L2_STD_SECAM) | ||
792 | tun->flags |= VIDEO_TUNER_SECAM; | ||
793 | } | ||
850 | 794 | ||
851 | if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) | 795 | err = drv(inode, file, VIDIOC_G_STD, &sid); |
852 | aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; | 796 | if (err < 0) |
853 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) | 797 | dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); |
854 | aud->mode = VIDEO_SOUND_STEREO; | 798 | if (err == 0) { |
855 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) | 799 | if (sid & V4L2_STD_PAL) |
856 | aud->mode = VIDEO_SOUND_MONO; | 800 | tun->mode = VIDEO_MODE_PAL; |
857 | break; | 801 | if (sid & V4L2_STD_NTSC) |
802 | tun->mode = VIDEO_MODE_NTSC; | ||
803 | if (sid & V4L2_STD_SECAM) | ||
804 | tun->mode = VIDEO_MODE_SECAM; | ||
858 | } | 805 | } |
859 | case VIDIOCSAUDIO: /* set audio controls */ | ||
860 | { | ||
861 | struct video_audio *aud = arg; | ||
862 | 806 | ||
863 | memset(&aud2, 0, sizeof(aud2)); | 807 | if (tun2.capability & V4L2_TUNER_CAP_LOW) |
864 | memset(&tun2, 0, sizeof(tun2)); | 808 | tun->flags |= VIDEO_TUNER_LOW; |
809 | if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) | ||
810 | tun->flags |= VIDEO_TUNER_STEREO_ON; | ||
811 | tun->signal = tun2.signal; | ||
812 | done: | ||
813 | return err; | ||
814 | } | ||
865 | 815 | ||
866 | aud2.index = aud->audio; | 816 | static noinline int v4l1_compat_select_tuner( |
867 | err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); | 817 | struct video_tuner *tun, |
868 | if (err < 0) { | 818 | struct inode *inode, |
869 | dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); | 819 | struct file *file, |
870 | break; | 820 | v4l2_kioctl drv) |
871 | } | 821 | { |
822 | int err; | ||
823 | struct v4l2_tuner t;/*84 bytes on x86_64*/ | ||
824 | memset(&t, 0, sizeof(t)); | ||
872 | 825 | ||
873 | set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, | 826 | t.index = tun->tuner; |
874 | aud->volume, drv); | 827 | |
875 | set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, | 828 | err = drv(inode, file, VIDIOC_S_INPUT, &t); |
876 | aud->bass, drv); | 829 | if (err < 0) |
877 | set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, | 830 | dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); |
878 | aud->treble, drv); | 831 | return err; |
879 | set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, | 832 | } |
880 | aud->balance, drv); | 833 | |
881 | set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, | 834 | static noinline int v4l1_compat_get_frequency( |
882 | !!(aud->flags & VIDEO_AUDIO_MUTE), drv); | 835 | unsigned long *freq, |
883 | 836 | struct inode *inode, | |
884 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | 837 | struct file *file, |
885 | if (err < 0) | 838 | v4l2_kioctl drv) |
886 | dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); | 839 | { |
887 | if (err == 0) { | 840 | int err; |
888 | switch (aud->mode) { | 841 | struct v4l2_frequency freq2; |
889 | default: | 842 | memset(&freq2, 0, sizeof(freq2)); |
890 | case VIDEO_SOUND_MONO: | 843 | |
891 | case VIDEO_SOUND_LANG1: | 844 | freq2.tuner = 0; |
892 | tun2.audmode = V4L2_TUNER_MODE_MONO; | 845 | err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); |
893 | break; | 846 | if (err < 0) |
894 | case VIDEO_SOUND_STEREO: | 847 | dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); |
895 | tun2.audmode = V4L2_TUNER_MODE_STEREO; | 848 | if (0 == err) |
896 | break; | 849 | *freq = freq2.frequency; |
897 | case VIDEO_SOUND_LANG2: | 850 | return err; |
898 | tun2.audmode = V4L2_TUNER_MODE_LANG2; | 851 | } |
899 | break; | 852 | |
900 | } | 853 | static noinline int v4l1_compat_set_frequency( |
901 | err = drv(inode, file, VIDIOC_S_TUNER, &tun2); | 854 | unsigned long *freq, |
902 | if (err < 0) | 855 | struct inode *inode, |
903 | dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); | 856 | struct file *file, |
904 | } | 857 | v4l2_kioctl drv) |
858 | { | ||
859 | int err; | ||
860 | struct v4l2_frequency freq2; | ||
861 | memset(&freq2, 0, sizeof(freq2)); | ||
862 | |||
863 | drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); | ||
864 | freq2.frequency = *freq; | ||
865 | err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); | ||
866 | if (err < 0) | ||
867 | dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); | ||
868 | return err; | ||
869 | } | ||
870 | |||
871 | static noinline int v4l1_compat_get_audio( | ||
872 | struct video_audio *aud, | ||
873 | struct inode *inode, | ||
874 | struct file *file, | ||
875 | v4l2_kioctl drv) | ||
876 | { | ||
877 | int err, i; | ||
878 | struct v4l2_queryctrl qctrl2; | ||
879 | struct v4l2_audio aud2; | ||
880 | struct v4l2_tuner tun2; | ||
881 | memset(&aud2, 0, sizeof(aud2)); | ||
882 | |||
883 | err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); | ||
884 | if (err < 0) { | ||
885 | dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); | ||
886 | goto done; | ||
887 | } | ||
888 | memcpy(aud->name, aud2.name, | ||
889 | min(sizeof(aud->name), sizeof(aud2.name))); | ||
890 | aud->name[sizeof(aud->name) - 1] = 0; | ||
891 | aud->audio = aud2.index; | ||
892 | aud->flags = 0; | ||
893 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); | ||
894 | if (i >= 0) { | ||
895 | aud->volume = i; | ||
896 | aud->flags |= VIDEO_AUDIO_VOLUME; | ||
897 | } | ||
898 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); | ||
899 | if (i >= 0) { | ||
900 | aud->bass = i; | ||
901 | aud->flags |= VIDEO_AUDIO_BASS; | ||
902 | } | ||
903 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); | ||
904 | if (i >= 0) { | ||
905 | aud->treble = i; | ||
906 | aud->flags |= VIDEO_AUDIO_TREBLE; | ||
907 | } | ||
908 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); | ||
909 | if (i >= 0) { | ||
910 | aud->balance = i; | ||
911 | aud->flags |= VIDEO_AUDIO_BALANCE; | ||
912 | } | ||
913 | i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); | ||
914 | if (i >= 0) { | ||
915 | if (i) | ||
916 | aud->flags |= VIDEO_AUDIO_MUTE; | ||
917 | aud->flags |= VIDEO_AUDIO_MUTABLE; | ||
918 | } | ||
919 | aud->step = 1; | ||
920 | qctrl2.id = V4L2_CID_AUDIO_VOLUME; | ||
921 | if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && | ||
922 | !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) | ||
923 | aud->step = qctrl2.step; | ||
924 | aud->mode = 0; | ||
925 | |||
926 | memset(&tun2, 0, sizeof(tun2)); | ||
927 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | ||
928 | if (err < 0) { | ||
929 | dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); | ||
905 | err = 0; | 930 | err = 0; |
906 | break; | 931 | goto done; |
907 | } | 932 | } |
908 | case VIDIOCMCAPTURE: /* capture a frame */ | ||
909 | { | ||
910 | struct video_mmap *mm = arg; | ||
911 | 933 | ||
912 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 934 | if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) |
913 | if (!fmt2) { | 935 | aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; |
914 | err = -ENOMEM; | 936 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) |
915 | break; | 937 | aud->mode = VIDEO_SOUND_STEREO; |
916 | } | 938 | else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) |
917 | memset(&buf2, 0, sizeof(buf2)); | 939 | aud->mode = VIDEO_SOUND_MONO; |
940 | done: | ||
941 | return err; | ||
942 | } | ||
918 | 943 | ||
919 | fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 944 | static noinline int v4l1_compat_set_audio( |
920 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | 945 | struct video_audio *aud, |
921 | if (err < 0) { | 946 | struct inode *inode, |
922 | dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); | 947 | struct file *file, |
948 | v4l2_kioctl drv) | ||
949 | { | ||
950 | int err; | ||
951 | struct v4l2_audio aud2; | ||
952 | struct v4l2_tuner tun2; | ||
953 | |||
954 | memset(&aud2, 0, sizeof(aud2)); | ||
955 | memset(&tun2, 0, sizeof(tun2)); | ||
956 | |||
957 | aud2.index = aud->audio; | ||
958 | err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); | ||
959 | if (err < 0) { | ||
960 | dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); | ||
961 | goto done; | ||
962 | } | ||
963 | |||
964 | set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, | ||
965 | aud->volume, drv); | ||
966 | set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, | ||
967 | aud->bass, drv); | ||
968 | set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, | ||
969 | aud->treble, drv); | ||
970 | set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, | ||
971 | aud->balance, drv); | ||
972 | set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, | ||
973 | !!(aud->flags & VIDEO_AUDIO_MUTE), drv); | ||
974 | |||
975 | err = drv(inode, file, VIDIOC_G_TUNER, &tun2); | ||
976 | if (err < 0) | ||
977 | dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); | ||
978 | if (err == 0) { | ||
979 | switch (aud->mode) { | ||
980 | default: | ||
981 | case VIDEO_SOUND_MONO: | ||
982 | case VIDEO_SOUND_LANG1: | ||
983 | tun2.audmode = V4L2_TUNER_MODE_MONO; | ||
923 | break; | 984 | break; |
924 | } | 985 | case VIDEO_SOUND_STEREO: |
925 | if (mm->width != fmt2->fmt.pix.width || | 986 | tun2.audmode = V4L2_TUNER_MODE_STEREO; |
926 | mm->height != fmt2->fmt.pix.height || | ||
927 | palette_to_pixelformat(mm->format) != | ||
928 | fmt2->fmt.pix.pixelformat) { | ||
929 | /* New capture format... */ | ||
930 | fmt2->fmt.pix.width = mm->width; | ||
931 | fmt2->fmt.pix.height = mm->height; | ||
932 | fmt2->fmt.pix.pixelformat = | ||
933 | palette_to_pixelformat(mm->format); | ||
934 | fmt2->fmt.pix.field = V4L2_FIELD_ANY; | ||
935 | fmt2->fmt.pix.bytesperline = 0; | ||
936 | err = drv(inode, file, VIDIOC_S_FMT, fmt2); | ||
937 | if (err < 0) { | ||
938 | dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); | ||
939 | break; | ||
940 | } | ||
941 | } | ||
942 | buf2.index = mm->frame; | ||
943 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
944 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | ||
945 | if (err < 0) { | ||
946 | dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); | ||
947 | break; | 987 | break; |
948 | } | 988 | case VIDEO_SOUND_LANG2: |
949 | err = drv(inode, file, VIDIOC_QBUF, &buf2); | 989 | tun2.audmode = V4L2_TUNER_MODE_LANG2; |
950 | if (err < 0) { | ||
951 | dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); | ||
952 | break; | 990 | break; |
953 | } | 991 | } |
954 | err = drv(inode, file, VIDIOC_STREAMON, &captype); | 992 | err = drv(inode, file, VIDIOC_S_TUNER, &tun2); |
955 | if (err < 0) | 993 | if (err < 0) |
956 | dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); | 994 | dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); |
957 | break; | ||
958 | } | 995 | } |
959 | case VIDIOCSYNC: /* wait for a frame */ | 996 | err = 0; |
960 | { | 997 | done: |
961 | int *i = arg; | 998 | return err; |
999 | } | ||
962 | 1000 | ||
963 | memset(&buf2, 0, sizeof(buf2)); | 1001 | static noinline int v4l1_compat_capture_frame( |
964 | buf2.index = *i; | 1002 | struct video_mmap *mm, |
965 | buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1003 | struct inode *inode, |
966 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | 1004 | struct file *file, |
967 | if (err < 0) { | 1005 | v4l2_kioctl drv) |
968 | /* No such buffer */ | 1006 | { |
969 | dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); | 1007 | int err; |
970 | break; | 1008 | enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
971 | } | 1009 | struct v4l2_buffer buf; |
972 | if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) { | 1010 | struct v4l2_format *fmt; |
973 | /* Buffer is not mapped */ | ||
974 | err = -EINVAL; | ||
975 | break; | ||
976 | } | ||
977 | 1011 | ||
978 | /* make sure capture actually runs so we don't block forever */ | 1012 | fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); |
979 | err = drv(inode, file, VIDIOC_STREAMON, &captype); | 1013 | if (!fmt) { |
1014 | err = -ENOMEM; | ||
1015 | return err; | ||
1016 | } | ||
1017 | memset(&buf, 0, sizeof(buf)); | ||
1018 | |||
1019 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1020 | err = drv(inode, file, VIDIOC_G_FMT, fmt); | ||
1021 | if (err < 0) { | ||
1022 | dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); | ||
1023 | goto done; | ||
1024 | } | ||
1025 | if (mm->width != fmt->fmt.pix.width || | ||
1026 | mm->height != fmt->fmt.pix.height || | ||
1027 | palette_to_pixelformat(mm->format) != | ||
1028 | fmt->fmt.pix.pixelformat) { | ||
1029 | /* New capture format... */ | ||
1030 | fmt->fmt.pix.width = mm->width; | ||
1031 | fmt->fmt.pix.height = mm->height; | ||
1032 | fmt->fmt.pix.pixelformat = | ||
1033 | palette_to_pixelformat(mm->format); | ||
1034 | fmt->fmt.pix.field = V4L2_FIELD_ANY; | ||
1035 | fmt->fmt.pix.bytesperline = 0; | ||
1036 | err = drv(inode, file, VIDIOC_S_FMT, fmt); | ||
980 | if (err < 0) { | 1037 | if (err < 0) { |
981 | dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); | 1038 | dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); |
982 | break; | 1039 | goto done; |
983 | } | 1040 | } |
1041 | } | ||
1042 | buf.index = mm->frame; | ||
1043 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1044 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf); | ||
1045 | if (err < 0) { | ||
1046 | dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); | ||
1047 | goto done; | ||
1048 | } | ||
1049 | err = drv(inode, file, VIDIOC_QBUF, &buf); | ||
1050 | if (err < 0) { | ||
1051 | dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); | ||
1052 | goto done; | ||
1053 | } | ||
1054 | err = drv(inode, file, VIDIOC_STREAMON, &captype); | ||
1055 | if (err < 0) | ||
1056 | dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); | ||
1057 | done: | ||
1058 | kfree(fmt); | ||
1059 | return err; | ||
1060 | } | ||
984 | 1061 | ||
985 | /* Loop as long as the buffer is queued, but not done */ | 1062 | static noinline int v4l1_compat_sync( |
986 | while ((buf2.flags & | 1063 | int *i, |
987 | (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) | 1064 | struct inode *inode, |
988 | == V4L2_BUF_FLAG_QUEUED) { | 1065 | struct file *file, |
989 | err = poll_one(file); | 1066 | v4l2_kioctl drv) |
990 | if (err < 0 || /* error or sleep was interrupted */ | 1067 | { |
991 | err == 0) /* timeout? Shouldn't occur. */ | 1068 | int err; |
992 | break; | 1069 | enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
993 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); | 1070 | struct v4l2_buffer buf; |
994 | if (err < 0) | 1071 | |
995 | dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); | 1072 | memset(&buf, 0, sizeof(buf)); |
996 | } | 1073 | buf.index = *i; |
997 | if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */ | 1074 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
998 | break; | 1075 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf); |
999 | do { | 1076 | if (err < 0) { |
1000 | err = drv(inode, file, VIDIOC_DQBUF, &buf2); | 1077 | /* No such buffer */ |
1001 | if (err < 0) | 1078 | dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); |
1002 | dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); | 1079 | goto done; |
1003 | } while (err == 0 && buf2.index != *i); | 1080 | } |
1004 | break; | 1081 | if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { |
1082 | /* Buffer is not mapped */ | ||
1083 | err = -EINVAL; | ||
1084 | goto done; | ||
1005 | } | 1085 | } |
1006 | 1086 | ||
1007 | case VIDIOCGVBIFMT: /* query VBI data capture format */ | 1087 | /* make sure capture actually runs so we don't block forever */ |
1008 | { | 1088 | err = drv(inode, file, VIDIOC_STREAMON, &captype); |
1009 | struct vbi_format *fmt = arg; | 1089 | if (err < 0) { |
1090 | dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); | ||
1091 | goto done; | ||
1092 | } | ||
1010 | 1093 | ||
1011 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 1094 | /* Loop as long as the buffer is queued, but not done */ |
1012 | if (!fmt2) { | 1095 | while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) |
1013 | err = -ENOMEM; | 1096 | == V4L2_BUF_FLAG_QUEUED) { |
1097 | err = poll_one(file); | ||
1098 | if (err < 0 || /* error or sleep was interrupted */ | ||
1099 | err == 0) /* timeout? Shouldn't occur. */ | ||
1014 | break; | 1100 | break; |
1015 | } | 1101 | err = drv(inode, file, VIDIOC_QUERYBUF, &buf); |
1016 | fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; | 1102 | if (err < 0) |
1103 | dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); | ||
1104 | } | ||
1105 | if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ | ||
1106 | goto done; | ||
1107 | do { | ||
1108 | err = drv(inode, file, VIDIOC_DQBUF, &buf); | ||
1109 | if (err < 0) | ||
1110 | dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); | ||
1111 | } while (err == 0 && buf.index != *i); | ||
1112 | done: | ||
1113 | return err; | ||
1114 | } | ||
1017 | 1115 | ||
1018 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); | 1116 | static noinline int v4l1_compat_get_vbi_format( |
1019 | if (err < 0) { | 1117 | struct vbi_format *fmt, |
1020 | dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); | 1118 | struct inode *inode, |
1021 | break; | 1119 | struct file *file, |
1022 | } | 1120 | v4l2_kioctl drv) |
1023 | if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { | 1121 | { |
1024 | err = -EINVAL; | 1122 | int err; |
1025 | break; | 1123 | struct v4l2_format *fmt2; |
1026 | } | 1124 | |
1027 | memset(fmt, 0, sizeof(*fmt)); | 1125 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); |
1028 | fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; | 1126 | if (!fmt2) { |
1029 | fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; | 1127 | err = -ENOMEM; |
1030 | fmt->sample_format = VIDEO_PALETTE_RAW; | 1128 | return err; |
1031 | fmt->start[0] = fmt2->fmt.vbi.start[0]; | ||
1032 | fmt->count[0] = fmt2->fmt.vbi.count[0]; | ||
1033 | fmt->start[1] = fmt2->fmt.vbi.start[1]; | ||
1034 | fmt->count[1] = fmt2->fmt.vbi.count[1]; | ||
1035 | fmt->flags = fmt2->fmt.vbi.flags & 0x03; | ||
1036 | break; | ||
1037 | } | 1129 | } |
1038 | case VIDIOCSVBIFMT: | 1130 | fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; |
1039 | { | ||
1040 | struct vbi_format *fmt = arg; | ||
1041 | 1131 | ||
1042 | if (VIDEO_PALETTE_RAW != fmt->sample_format) { | 1132 | err = drv(inode, file, VIDIOC_G_FMT, fmt2); |
1043 | err = -EINVAL; | 1133 | if (err < 0) { |
1044 | break; | 1134 | dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); |
1045 | } | 1135 | goto done; |
1136 | } | ||
1137 | if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { | ||
1138 | err = -EINVAL; | ||
1139 | goto done; | ||
1140 | } | ||
1141 | memset(fmt, 0, sizeof(*fmt)); | ||
1142 | fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; | ||
1143 | fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; | ||
1144 | fmt->sample_format = VIDEO_PALETTE_RAW; | ||
1145 | fmt->start[0] = fmt2->fmt.vbi.start[0]; | ||
1146 | fmt->count[0] = fmt2->fmt.vbi.count[0]; | ||
1147 | fmt->start[1] = fmt2->fmt.vbi.start[1]; | ||
1148 | fmt->count[1] = fmt2->fmt.vbi.count[1]; | ||
1149 | fmt->flags = fmt2->fmt.vbi.flags & 0x03; | ||
1150 | done: | ||
1151 | kfree(fmt2); | ||
1152 | return err; | ||
1153 | } | ||
1046 | 1154 | ||
1047 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); | 1155 | static noinline int v4l1_compat_set_vbi_format( |
1048 | if (!fmt2) { | 1156 | struct vbi_format *fmt, |
1049 | err = -ENOMEM; | 1157 | struct inode *inode, |
1050 | break; | 1158 | struct file *file, |
1051 | } | 1159 | v4l2_kioctl drv) |
1052 | fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; | 1160 | { |
1053 | fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; | 1161 | int err; |
1054 | fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; | 1162 | struct v4l2_format *fmt2 = NULL; |
1055 | fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1056 | fmt2->fmt.vbi.start[0] = fmt->start[0]; | ||
1057 | fmt2->fmt.vbi.count[0] = fmt->count[0]; | ||
1058 | fmt2->fmt.vbi.start[1] = fmt->start[1]; | ||
1059 | fmt2->fmt.vbi.count[1] = fmt->count[1]; | ||
1060 | fmt2->fmt.vbi.flags = fmt->flags; | ||
1061 | err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); | ||
1062 | if (err < 0) { | ||
1063 | dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); | ||
1064 | break; | ||
1065 | } | ||
1066 | 1163 | ||
1067 | if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || | 1164 | if (VIDEO_PALETTE_RAW != fmt->sample_format) { |
1068 | fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || | 1165 | err = -EINVAL; |
1069 | fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || | 1166 | return err; |
1070 | fmt2->fmt.vbi.start[0] != fmt->start[0] || | 1167 | } |
1071 | fmt2->fmt.vbi.count[0] != fmt->count[0] || | 1168 | |
1072 | fmt2->fmt.vbi.start[1] != fmt->start[1] || | 1169 | fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); |
1073 | fmt2->fmt.vbi.count[1] != fmt->count[1] || | 1170 | if (!fmt2) { |
1074 | fmt2->fmt.vbi.flags != fmt->flags) { | 1171 | err = -ENOMEM; |
1075 | err = -EINVAL; | 1172 | return err; |
1076 | break; | ||
1077 | } | ||
1078 | err = drv(inode, file, VIDIOC_S_FMT, fmt2); | ||
1079 | if (err < 0) | ||
1080 | dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); | ||
1081 | break; | ||
1082 | } | 1173 | } |
1174 | fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1175 | fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; | ||
1176 | fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; | ||
1177 | fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1178 | fmt2->fmt.vbi.start[0] = fmt->start[0]; | ||
1179 | fmt2->fmt.vbi.count[0] = fmt->count[0]; | ||
1180 | fmt2->fmt.vbi.start[1] = fmt->start[1]; | ||
1181 | fmt2->fmt.vbi.count[1] = fmt->count[1]; | ||
1182 | fmt2->fmt.vbi.flags = fmt->flags; | ||
1183 | err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); | ||
1184 | if (err < 0) { | ||
1185 | dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); | ||
1186 | goto done; | ||
1187 | } | ||
1188 | |||
1189 | if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || | ||
1190 | fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || | ||
1191 | fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || | ||
1192 | fmt2->fmt.vbi.start[0] != fmt->start[0] || | ||
1193 | fmt2->fmt.vbi.count[0] != fmt->count[0] || | ||
1194 | fmt2->fmt.vbi.start[1] != fmt->start[1] || | ||
1195 | fmt2->fmt.vbi.count[1] != fmt->count[1] || | ||
1196 | fmt2->fmt.vbi.flags != fmt->flags) { | ||
1197 | err = -EINVAL; | ||
1198 | goto done; | ||
1199 | } | ||
1200 | err = drv(inode, file, VIDIOC_S_FMT, fmt2); | ||
1201 | if (err < 0) | ||
1202 | dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); | ||
1203 | done: | ||
1204 | kfree(fmt2); | ||
1205 | return err; | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | * This function is exported. | ||
1210 | */ | ||
1211 | int | ||
1212 | v4l_compat_translate_ioctl(struct inode *inode, | ||
1213 | struct file *file, | ||
1214 | int cmd, | ||
1215 | void *arg, | ||
1216 | v4l2_kioctl drv) | ||
1217 | { | ||
1218 | int err; | ||
1083 | 1219 | ||
1220 | switch (cmd) { | ||
1221 | case VIDIOCGCAP: /* capability */ | ||
1222 | err = v4l1_compat_get_capabilities(arg, inode, file, drv); | ||
1223 | break; | ||
1224 | case VIDIOCGFBUF: /* get frame buffer */ | ||
1225 | err = v4l1_compat_get_frame_buffer(arg, inode, file, drv); | ||
1226 | break; | ||
1227 | case VIDIOCSFBUF: /* set frame buffer */ | ||
1228 | err = v4l1_compat_set_frame_buffer(arg, inode, file, drv); | ||
1229 | break; | ||
1230 | case VIDIOCGWIN: /* get window or capture dimensions */ | ||
1231 | err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv); | ||
1232 | break; | ||
1233 | case VIDIOCSWIN: /* set window and/or capture dimensions */ | ||
1234 | err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv); | ||
1235 | break; | ||
1236 | case VIDIOCCAPTURE: /* turn on/off preview */ | ||
1237 | err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv); | ||
1238 | break; | ||
1239 | case VIDIOCGCHAN: /* get input information */ | ||
1240 | err = v4l1_compat_get_input_info(arg, inode, file, drv); | ||
1241 | break; | ||
1242 | case VIDIOCSCHAN: /* set input */ | ||
1243 | err = v4l1_compat_set_input(arg, inode, file, drv); | ||
1244 | break; | ||
1245 | case VIDIOCGPICT: /* get tone controls & partial capture format */ | ||
1246 | err = v4l1_compat_get_picture(arg, inode, file, drv); | ||
1247 | break; | ||
1248 | case VIDIOCSPICT: /* set tone controls & partial capture format */ | ||
1249 | err = v4l1_compat_set_picture(arg, inode, file, drv); | ||
1250 | break; | ||
1251 | case VIDIOCGTUNER: /* get tuner information */ | ||
1252 | err = v4l1_compat_get_tuner(arg, inode, file, drv); | ||
1253 | break; | ||
1254 | case VIDIOCSTUNER: /* select a tuner input */ | ||
1255 | err = v4l1_compat_select_tuner(arg, inode, file, drv); | ||
1256 | break; | ||
1257 | case VIDIOCGFREQ: /* get frequency */ | ||
1258 | err = v4l1_compat_get_frequency(arg, inode, file, drv); | ||
1259 | break; | ||
1260 | case VIDIOCSFREQ: /* set frequency */ | ||
1261 | err = v4l1_compat_set_frequency(arg, inode, file, drv); | ||
1262 | break; | ||
1263 | case VIDIOCGAUDIO: /* get audio properties/controls */ | ||
1264 | err = v4l1_compat_get_audio(arg, inode, file, drv); | ||
1265 | break; | ||
1266 | case VIDIOCSAUDIO: /* set audio controls */ | ||
1267 | err = v4l1_compat_set_audio(arg, inode, file, drv); | ||
1268 | break; | ||
1269 | case VIDIOCMCAPTURE: /* capture a frame */ | ||
1270 | err = v4l1_compat_capture_frame(arg, inode, file, drv); | ||
1271 | break; | ||
1272 | case VIDIOCSYNC: /* wait for a frame */ | ||
1273 | err = v4l1_compat_sync(arg, inode, file, drv); | ||
1274 | break; | ||
1275 | case VIDIOCGVBIFMT: /* query VBI data capture format */ | ||
1276 | err = v4l1_compat_get_vbi_format(arg, inode, file, drv); | ||
1277 | break; | ||
1278 | case VIDIOCSVBIFMT: | ||
1279 | err = v4l1_compat_set_vbi_format(arg, inode, file, drv); | ||
1280 | break; | ||
1084 | default: | 1281 | default: |
1085 | err = -ENOIOCTLCMD; | 1282 | err = -ENOIOCTLCMD; |
1086 | break; | 1283 | break; |
1087 | } | 1284 | } |
1088 | 1285 | ||
1089 | kfree(cap2); | ||
1090 | kfree(fmt2); | ||
1091 | return err; | 1286 | return err; |
1092 | } | 1287 | } |
1093 | EXPORT_SYMBOL(v4l_compat_translate_ioctl); | 1288 | EXPORT_SYMBOL(v4l_compat_translate_ioctl); |