aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/pwc/pwc-if.c22
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c1034
-rw-r--r--drivers/media/video/pwc/pwc.h3
3 files changed, 494 insertions, 565 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 4aa70faaae8c..780af5f81642 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -151,8 +151,6 @@ static int pwc_video_close(struct file *file);
151static ssize_t pwc_video_read(struct file *file, char __user *buf, 151static ssize_t pwc_video_read(struct file *file, char __user *buf,
152 size_t count, loff_t *ppos); 152 size_t count, loff_t *ppos);
153static unsigned int pwc_video_poll(struct file *file, poll_table *wait); 153static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
154static long pwc_video_ioctl(struct file *file,
155 unsigned int ioctlnr, unsigned long arg);
156static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); 154static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
157 155
158static const struct v4l2_file_operations pwc_fops = { 156static const struct v4l2_file_operations pwc_fops = {
@@ -162,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = {
162 .read = pwc_video_read, 160 .read = pwc_video_read,
163 .poll = pwc_video_poll, 161 .poll = pwc_video_poll,
164 .mmap = pwc_video_mmap, 162 .mmap = pwc_video_mmap,
165 .unlocked_ioctl = pwc_video_ioctl, 163 .unlocked_ioctl = video_ioctl2,
166}; 164};
167static struct video_device pwc_template = { 165static struct video_device pwc_template = {
168 .name = "Philips Webcam", /* Filled in later */ 166 .name = "Philips Webcam", /* Filled in later */
@@ -1378,23 +1376,6 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
1378 return 0; 1376 return 0;
1379} 1377}
1380 1378
1381static long pwc_video_ioctl(struct file *file,
1382 unsigned int cmd, unsigned long arg)
1383{
1384 struct video_device *vdev = file->private_data;
1385 struct pwc_device *pdev;
1386 long r = -ENODEV;
1387
1388 if (!vdev)
1389 goto out;
1390 pdev = video_get_drvdata(vdev);
1391
1392 if (!pdev->unplugged)
1393 r = video_usercopy(file, cmd, arg, pwc_video_do_ioctl);
1394out:
1395 return r;
1396}
1397
1398static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) 1379static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
1399{ 1380{
1400 struct video_device *vdev = file->private_data; 1381 struct video_device *vdev = file->private_data;
@@ -1744,6 +1725,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1744 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); 1725 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
1745 pdev->vdev->parent = &intf->dev; 1726 pdev->vdev->parent = &intf->dev;
1746 pdev->vdev->lock = &pdev->modlock; 1727 pdev->vdev->lock = &pdev->modlock;
1728 pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
1747 strcpy(pdev->vdev->name, name); 1729 strcpy(pdev->vdev->name, name);
1748 video_set_drvdata(pdev->vdev, pdev); 1730 video_set_drvdata(pdev->vdev, pdev);
1749 1731
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 8a7e52c3b8f5..68a5313a52d5 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -341,606 +341,554 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
341 341
342} 342}
343 343
344long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) 344static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
345{ 345{
346 struct video_device *vdev = video_devdata(file); 346 struct video_device *vdev = video_devdata(file);
347 struct pwc_device *pdev; 347 struct pwc_device *pdev = video_drvdata(file);
348 DECLARE_WAITQUEUE(wait, current); 348
349 349 strcpy(cap->driver, PWC_NAME);
350 if (vdev == NULL) 350 strlcpy(cap->card, vdev->name, sizeof(cap->card));
351 return -EFAULT; 351 usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
352 pdev = video_get_drvdata(vdev); 352 cap->version = PWC_VERSION_CODE;
353 if (pdev == NULL) 353 cap->capabilities =
354 return -EFAULT; 354 V4L2_CAP_VIDEO_CAPTURE |
355 V4L2_CAP_STREAMING |
356 V4L2_CAP_READWRITE;
357 return 0;
358}
355 359
356#ifdef CONFIG_USB_PWC_DEBUG 360static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
357 if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) { 361{
358 v4l_printk_ioctl(cmd); 362 if (i->index) /* Only one INPUT is supported */
359 printk("\n"); 363 return -EINVAL;
360 }
361#endif
362
363
364 switch (cmd) {
365 /* V4L2 Layer */
366 case VIDIOC_QUERYCAP:
367 {
368 struct v4l2_capability *cap = arg;
369
370 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
371 "try to use the v4l2 layer\n");
372 strcpy(cap->driver,PWC_NAME);
373 strlcpy(cap->card, vdev->name, sizeof(cap->card));
374 usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
375 cap->version = PWC_VERSION_CODE;
376 cap->capabilities =
377 V4L2_CAP_VIDEO_CAPTURE |
378 V4L2_CAP_STREAMING |
379 V4L2_CAP_READWRITE;
380 return 0;
381 }
382 364
383 case VIDIOC_ENUMINPUT: 365 strcpy(i->name, "usb");
384 { 366 return 0;
385 struct v4l2_input *i = arg; 367}
386 368
387 if ( i->index ) /* Only one INPUT is supported */ 369static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
388 return -EINVAL; 370{
371 *i = 0;
372 return 0;
373}
389 374
390 memset(i, 0, sizeof(struct v4l2_input)); 375static int pwc_s_input(struct file *file, void *fh, unsigned int i)
391 strcpy(i->name, "usb"); 376{
392 return 0; 377 return i ? -EINVAL : 0;
393 } 378}
394 379
395 case VIDIOC_G_INPUT: 380static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
396 { 381{
397 int *i = arg; 382 int i;
398 *i = 0; /* Only one INPUT is supported */
399 return 0;
400 }
401 case VIDIOC_S_INPUT:
402 {
403 int *i = arg;
404 383
405 if ( *i ) { /* Only one INPUT is supported */ 384 for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) {
406 PWC_DEBUG_IOCTL("Only one input source is"\ 385 if (pwc_controls[i].id == c->id) {
407 " supported with this webcam.\n"); 386 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
408 return -EINVAL; 387 memcpy(c, &pwc_controls[i], sizeof(struct v4l2_queryctrl));
409 }
410 return 0; 388 return 0;
411 } 389 }
390 }
391 return -EINVAL;
392}
412 393
413 /* TODO: */ 394static int pwc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
414 case VIDIOC_QUERYCTRL: 395{
415 { 396 struct pwc_device *pdev = video_drvdata(file);
416 struct v4l2_queryctrl *c = arg; 397 int ret;
417 int i;
418
419 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
420 for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
421 if (pwc_controls[i].id == c->id) {
422 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
423 memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
424 return 0;
425 }
426 }
427 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
428 398
399 switch (c->id) {
400 case V4L2_CID_BRIGHTNESS:
401 c->value = pwc_get_brightness(pdev);
402 if (c->value < 0)
429 return -EINVAL; 403 return -EINVAL;
430 } 404 return 0;
431 case VIDIOC_G_CTRL: 405 case V4L2_CID_CONTRAST:
432 { 406 c->value = pwc_get_contrast(pdev);
433 struct v4l2_control *c = arg; 407 if (c->value < 0)
434 int ret;
435
436 switch (c->id)
437 {
438 case V4L2_CID_BRIGHTNESS:
439 c->value = pwc_get_brightness(pdev);
440 if (c->value<0)
441 return -EINVAL;
442 return 0;
443 case V4L2_CID_CONTRAST:
444 c->value = pwc_get_contrast(pdev);
445 if (c->value<0)
446 return -EINVAL;
447 return 0;
448 case V4L2_CID_SATURATION:
449 ret = pwc_get_saturation(pdev, &c->value);
450 if (ret<0)
451 return -EINVAL;
452 return 0;
453 case V4L2_CID_GAMMA:
454 c->value = pwc_get_gamma(pdev);
455 if (c->value<0)
456 return -EINVAL;
457 return 0;
458 case V4L2_CID_RED_BALANCE:
459 ret = pwc_get_red_gain(pdev, &c->value);
460 if (ret<0)
461 return -EINVAL;
462 c->value >>= 8;
463 return 0;
464 case V4L2_CID_BLUE_BALANCE:
465 ret = pwc_get_blue_gain(pdev, &c->value);
466 if (ret<0)
467 return -EINVAL;
468 c->value >>= 8;
469 return 0;
470 case V4L2_CID_AUTO_WHITE_BALANCE:
471 ret = pwc_get_awb(pdev);
472 if (ret<0)
473 return -EINVAL;
474 c->value = (ret == PWC_WB_MANUAL)?0:1;
475 return 0;
476 case V4L2_CID_GAIN:
477 ret = pwc_get_agc(pdev, &c->value);
478 if (ret<0)
479 return -EINVAL;
480 c->value >>= 8;
481 return 0;
482 case V4L2_CID_AUTOGAIN:
483 ret = pwc_get_agc(pdev, &c->value);
484 if (ret<0)
485 return -EINVAL;
486 c->value = (c->value < 0)?1:0;
487 return 0;
488 case V4L2_CID_EXPOSURE:
489 ret = pwc_get_shutter_speed(pdev, &c->value);
490 if (ret<0)
491 return -EINVAL;
492 return 0;
493 case V4L2_CID_PRIVATE_COLOUR_MODE:
494 ret = pwc_get_colour_mode(pdev, &c->value);
495 if (ret < 0)
496 return -EINVAL;
497 return 0;
498 case V4L2_CID_PRIVATE_AUTOCONTOUR:
499 ret = pwc_get_contour(pdev, &c->value);
500 if (ret < 0)
501 return -EINVAL;
502 c->value=(c->value == -1?1:0);
503 return 0;
504 case V4L2_CID_PRIVATE_CONTOUR:
505 ret = pwc_get_contour(pdev, &c->value);
506 if (ret < 0)
507 return -EINVAL;
508 c->value >>= 10;
509 return 0;
510 case V4L2_CID_PRIVATE_BACKLIGHT:
511 ret = pwc_get_backlight(pdev, &c->value);
512 if (ret < 0)
513 return -EINVAL;
514 return 0;
515 case V4L2_CID_PRIVATE_FLICKERLESS:
516 ret = pwc_get_flicker(pdev, &c->value);
517 if (ret < 0)
518 return -EINVAL;
519 c->value=(c->value?1:0);
520 return 0;
521 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
522 ret = pwc_get_dynamic_noise(pdev, &c->value);
523 if (ret < 0)
524 return -EINVAL;
525 return 0;
526
527 case V4L2_CID_PRIVATE_SAVE_USER:
528 case V4L2_CID_PRIVATE_RESTORE_USER:
529 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
530 return -EINVAL;
531 }
532 return -EINVAL; 408 return -EINVAL;
533 } 409 return 0;
534 case VIDIOC_S_CTRL: 410 case V4L2_CID_SATURATION:
535 { 411 ret = pwc_get_saturation(pdev, &c->value);
536 struct v4l2_control *c = arg; 412 if (ret < 0)
537 int ret;
538
539 switch (c->id)
540 {
541 case V4L2_CID_BRIGHTNESS:
542 c->value <<= 9;
543 ret = pwc_set_brightness(pdev, c->value);
544 if (ret<0)
545 return -EINVAL;
546 return 0;
547 case V4L2_CID_CONTRAST:
548 c->value <<= 10;
549 ret = pwc_set_contrast(pdev, c->value);
550 if (ret<0)
551 return -EINVAL;
552 return 0;
553 case V4L2_CID_SATURATION:
554 ret = pwc_set_saturation(pdev, c->value);
555 if (ret<0)
556 return -EINVAL;
557 return 0;
558 case V4L2_CID_GAMMA:
559 c->value <<= 11;
560 ret = pwc_set_gamma(pdev, c->value);
561 if (ret<0)
562 return -EINVAL;
563 return 0;
564 case V4L2_CID_RED_BALANCE:
565 c->value <<= 8;
566 ret = pwc_set_red_gain(pdev, c->value);
567 if (ret<0)
568 return -EINVAL;
569 return 0;
570 case V4L2_CID_BLUE_BALANCE:
571 c->value <<= 8;
572 ret = pwc_set_blue_gain(pdev, c->value);
573 if (ret<0)
574 return -EINVAL;
575 return 0;
576 case V4L2_CID_AUTO_WHITE_BALANCE:
577 c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
578 ret = pwc_set_awb(pdev, c->value);
579 if (ret<0)
580 return -EINVAL;
581 return 0;
582 case V4L2_CID_EXPOSURE:
583 c->value <<= 8;
584 ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
585 if (ret<0)
586 return -EINVAL;
587 return 0;
588 case V4L2_CID_AUTOGAIN:
589 /* autogain off means nothing without a gain */
590 if (c->value == 0)
591 return 0;
592 ret = pwc_set_agc(pdev, c->value, 0);
593 if (ret<0)
594 return -EINVAL;
595 return 0;
596 case V4L2_CID_GAIN:
597 c->value <<= 8;
598 ret = pwc_set_agc(pdev, 0, c->value);
599 if (ret<0)
600 return -EINVAL;
601 return 0;
602 case V4L2_CID_PRIVATE_SAVE_USER:
603 if (pwc_save_user(pdev))
604 return -EINVAL;
605 return 0;
606 case V4L2_CID_PRIVATE_RESTORE_USER:
607 if (pwc_restore_user(pdev))
608 return -EINVAL;
609 return 0;
610 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
611 if (pwc_restore_factory(pdev))
612 return -EINVAL;
613 return 0;
614 case V4L2_CID_PRIVATE_COLOUR_MODE:
615 ret = pwc_set_colour_mode(pdev, c->value);
616 if (ret < 0)
617 return -EINVAL;
618 return 0;
619 case V4L2_CID_PRIVATE_AUTOCONTOUR:
620 c->value=(c->value == 1)?-1:0;
621 ret = pwc_set_contour(pdev, c->value);
622 if (ret < 0)
623 return -EINVAL;
624 return 0;
625 case V4L2_CID_PRIVATE_CONTOUR:
626 c->value <<= 10;
627 ret = pwc_set_contour(pdev, c->value);
628 if (ret < 0)
629 return -EINVAL;
630 return 0;
631 case V4L2_CID_PRIVATE_BACKLIGHT:
632 ret = pwc_set_backlight(pdev, c->value);
633 if (ret < 0)
634 return -EINVAL;
635 return 0;
636 case V4L2_CID_PRIVATE_FLICKERLESS:
637 ret = pwc_set_flicker(pdev, c->value);
638 if (ret < 0)
639 return -EINVAL;
640 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
641 ret = pwc_set_dynamic_noise(pdev, c->value);
642 if (ret < 0)
643 return -EINVAL;
644 return 0;
645
646 }
647 return -EINVAL; 413 return -EINVAL;
648 } 414 return 0;
415 case V4L2_CID_GAMMA:
416 c->value = pwc_get_gamma(pdev);
417 if (c->value < 0)
418 return -EINVAL;
419 return 0;
420 case V4L2_CID_RED_BALANCE:
421 ret = pwc_get_red_gain(pdev, &c->value);
422 if (ret < 0)
423 return -EINVAL;
424 c->value >>= 8;
425 return 0;
426 case V4L2_CID_BLUE_BALANCE:
427 ret = pwc_get_blue_gain(pdev, &c->value);
428 if (ret < 0)
429 return -EINVAL;
430 c->value >>= 8;
431 return 0;
432 case V4L2_CID_AUTO_WHITE_BALANCE:
433 ret = pwc_get_awb(pdev);
434 if (ret < 0)
435 return -EINVAL;
436 c->value = (ret == PWC_WB_MANUAL) ? 0 : 1;
437 return 0;
438 case V4L2_CID_GAIN:
439 ret = pwc_get_agc(pdev, &c->value);
440 if (ret < 0)
441 return -EINVAL;
442 c->value >>= 8;
443 return 0;
444 case V4L2_CID_AUTOGAIN:
445 ret = pwc_get_agc(pdev, &c->value);
446 if (ret < 0)
447 return -EINVAL;
448 c->value = (c->value < 0) ? 1 : 0;
449 return 0;
450 case V4L2_CID_EXPOSURE:
451 ret = pwc_get_shutter_speed(pdev, &c->value);
452 if (ret < 0)
453 return -EINVAL;
454 return 0;
455 case V4L2_CID_PRIVATE_COLOUR_MODE:
456 ret = pwc_get_colour_mode(pdev, &c->value);
457 if (ret < 0)
458 return -EINVAL;
459 return 0;
460 case V4L2_CID_PRIVATE_AUTOCONTOUR:
461 ret = pwc_get_contour(pdev, &c->value);
462 if (ret < 0)
463 return -EINVAL;
464 c->value = (c->value == -1 ? 1 : 0);
465 return 0;
466 case V4L2_CID_PRIVATE_CONTOUR:
467 ret = pwc_get_contour(pdev, &c->value);
468 if (ret < 0)
469 return -EINVAL;
470 c->value >>= 10;
471 return 0;
472 case V4L2_CID_PRIVATE_BACKLIGHT:
473 ret = pwc_get_backlight(pdev, &c->value);
474 if (ret < 0)
475 return -EINVAL;
476 return 0;
477 case V4L2_CID_PRIVATE_FLICKERLESS:
478 ret = pwc_get_flicker(pdev, &c->value);
479 if (ret < 0)
480 return -EINVAL;
481 c->value = (c->value ? 1 : 0);
482 return 0;
483 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
484 ret = pwc_get_dynamic_noise(pdev, &c->value);
485 if (ret < 0)
486 return -EINVAL;
487 return 0;
649 488
650 case VIDIOC_ENUM_FMT: 489 case V4L2_CID_PRIVATE_SAVE_USER:
651 { 490 case V4L2_CID_PRIVATE_RESTORE_USER:
652 struct v4l2_fmtdesc *f = arg; 491 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
653 int index; 492 return -EINVAL;
654 493 }
655 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 494 return -EINVAL;
656 return -EINVAL; 495}
657
658 /* We only support two format: the raw format, and YUV */
659 index = f->index;
660 memset(f,0,sizeof(struct v4l2_fmtdesc));
661 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
662 f->index = index;
663 switch(index)
664 {
665 case 0:
666 /* RAW format */
667 f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
668 f->flags = V4L2_FMT_FLAG_COMPRESSED;
669 strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
670 break;
671 case 1:
672 f->pixelformat = V4L2_PIX_FMT_YUV420;
673 strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
674 break;
675 default:
676 return -EINVAL;
677 }
678 return 0;
679 }
680 496
681 case VIDIOC_G_FMT: 497static int pwc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
682 { 498{
683 struct v4l2_format *f = arg; 499 struct pwc_device *pdev = video_drvdata(file);
500 int ret;
501
502 switch (c->id) {
503 case V4L2_CID_BRIGHTNESS:
504 c->value <<= 9;
505 ret = pwc_set_brightness(pdev, c->value);
506 if (ret < 0)
507 return -EINVAL;
508 return 0;
509 case V4L2_CID_CONTRAST:
510 c->value <<= 10;
511 ret = pwc_set_contrast(pdev, c->value);
512 if (ret < 0)
513 return -EINVAL;
514 return 0;
515 case V4L2_CID_SATURATION:
516 ret = pwc_set_saturation(pdev, c->value);
517 if (ret < 0)
518 return -EINVAL;
519 return 0;
520 case V4L2_CID_GAMMA:
521 c->value <<= 11;
522 ret = pwc_set_gamma(pdev, c->value);
523 if (ret < 0)
524 return -EINVAL;
525 return 0;
526 case V4L2_CID_RED_BALANCE:
527 c->value <<= 8;
528 ret = pwc_set_red_gain(pdev, c->value);
529 if (ret < 0)
530 return -EINVAL;
531 return 0;
532 case V4L2_CID_BLUE_BALANCE:
533 c->value <<= 8;
534 ret = pwc_set_blue_gain(pdev, c->value);
535 if (ret < 0)
536 return -EINVAL;
537 return 0;
538 case V4L2_CID_AUTO_WHITE_BALANCE:
539 c->value = (c->value == 0) ? PWC_WB_MANUAL : PWC_WB_AUTO;
540 ret = pwc_set_awb(pdev, c->value);
541 if (ret < 0)
542 return -EINVAL;
543 return 0;
544 case V4L2_CID_EXPOSURE:
545 c->value <<= 8;
546 ret = pwc_set_shutter_speed(pdev, c->value ? 0 : 1, c->value);
547 if (ret < 0)
548 return -EINVAL;
549 return 0;
550 case V4L2_CID_AUTOGAIN:
551 /* autogain off means nothing without a gain */
552 if (c->value == 0)
553 return 0;
554 ret = pwc_set_agc(pdev, c->value, 0);
555 if (ret < 0)
556 return -EINVAL;
557 return 0;
558 case V4L2_CID_GAIN:
559 c->value <<= 8;
560 ret = pwc_set_agc(pdev, 0, c->value);
561 if (ret < 0)
562 return -EINVAL;
563 return 0;
564 case V4L2_CID_PRIVATE_SAVE_USER:
565 if (pwc_save_user(pdev))
566 return -EINVAL;
567 return 0;
568 case V4L2_CID_PRIVATE_RESTORE_USER:
569 if (pwc_restore_user(pdev))
570 return -EINVAL;
571 return 0;
572 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
573 if (pwc_restore_factory(pdev))
574 return -EINVAL;
575 return 0;
576 case V4L2_CID_PRIVATE_COLOUR_MODE:
577 ret = pwc_set_colour_mode(pdev, c->value);
578 if (ret < 0)
579 return -EINVAL;
580 return 0;
581 case V4L2_CID_PRIVATE_AUTOCONTOUR:
582 c->value = (c->value == 1) ? -1 : 0;
583 ret = pwc_set_contour(pdev, c->value);
584 if (ret < 0)
585 return -EINVAL;
586 return 0;
587 case V4L2_CID_PRIVATE_CONTOUR:
588 c->value <<= 10;
589 ret = pwc_set_contour(pdev, c->value);
590 if (ret < 0)
591 return -EINVAL;
592 return 0;
593 case V4L2_CID_PRIVATE_BACKLIGHT:
594 ret = pwc_set_backlight(pdev, c->value);
595 if (ret < 0)
596 return -EINVAL;
597 return 0;
598 case V4L2_CID_PRIVATE_FLICKERLESS:
599 ret = pwc_set_flicker(pdev, c->value);
600 if (ret < 0)
601 return -EINVAL;
602 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
603 ret = pwc_set_dynamic_noise(pdev, c->value);
604 if (ret < 0)
605 return -EINVAL;
606 return 0;
684 607
685 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y); 608 }
686 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 609 return -EINVAL;
687 return -EINVAL; 610}
688 611
689 pwc_vidioc_fill_fmt(pdev, f); 612static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
613{
614 struct pwc_device *pdev = video_drvdata(file);
615
616 /* We only support two format: the raw format, and YUV */
617 switch (f->index) {
618 case 0:
619 /* RAW format */
620 f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
621 f->flags = V4L2_FMT_FLAG_COMPRESSED;
622 strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
623 break;
624 case 1:
625 f->pixelformat = V4L2_PIX_FMT_YUV420;
626 strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
627 break;
628 default:
629 return -EINVAL;
630 }
631 return 0;
632}
690 633
691 return 0; 634static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
692 } 635{
636 struct pwc_device *pdev = video_drvdata(file);
693 637
694 case VIDIOC_TRY_FMT: 638 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
695 return pwc_vidioc_try_fmt(pdev, arg); 639 pdev->image.x, pdev->image.y);
640 pwc_vidioc_fill_fmt(pdev, f);
641 return 0;
642}
696 643
697 case VIDIOC_S_FMT: 644static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
698 return pwc_vidioc_set_fmt(pdev, arg); 645{
646 struct pwc_device *pdev = video_drvdata(file);
699 647
700 case VIDIOC_G_STD: 648 return pwc_vidioc_try_fmt(pdev, f);
701 { 649}
702 v4l2_std_id *std = arg;
703 *std = V4L2_STD_UNKNOWN;
704 return 0;
705 }
706 650
707 case VIDIOC_S_STD: 651static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
708 { 652{
709 v4l2_std_id *std = arg; 653 struct pwc_device *pdev = video_drvdata(file);
710 if (*std != V4L2_STD_UNKNOWN)
711 return -EINVAL;
712 return 0;
713 }
714 654
715 case VIDIOC_ENUMSTD: 655 return pwc_vidioc_set_fmt(pdev, f);
716 { 656}
717 struct v4l2_standard *std = arg;
718 if (std->index != 0)
719 return -EINVAL;
720 std->id = V4L2_STD_UNKNOWN;
721 strlcpy(std->name, "webcam", sizeof(std->name));
722 return 0;
723 }
724 657
725 case VIDIOC_REQBUFS: 658static int pwc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
726 { 659{
727 struct v4l2_requestbuffers *rb = arg; 660 int nbuffers;
728 int nbuffers;
729 661
730 PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count); 662 PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n", rb->count);
731 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 663 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
732 return -EINVAL; 664 return -EINVAL;
733 if (rb->memory != V4L2_MEMORY_MMAP) 665 if (rb->memory != V4L2_MEMORY_MMAP)
734 return -EINVAL; 666 return -EINVAL;
735 667
736 nbuffers = rb->count; 668 nbuffers = rb->count;
737 if (nbuffers < 2) 669 if (nbuffers < 2)
738 nbuffers = 2; 670 nbuffers = 2;
739 else if (nbuffers > pwc_mbufs) 671 else if (nbuffers > pwc_mbufs)
740 nbuffers = pwc_mbufs; 672 nbuffers = pwc_mbufs;
741 /* Force to use our # of buffers */ 673 /* Force to use our # of buffers */
742 rb->count = pwc_mbufs; 674 rb->count = pwc_mbufs;
743 return 0; 675 return 0;
744 } 676}
745 677
746 case VIDIOC_QUERYBUF: 678static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
747 { 679{
748 struct v4l2_buffer *buf = arg; 680 struct pwc_device *pdev = video_drvdata(file);
749 int index; 681 int index;
750 682
751 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index); 683 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n", buf->index);
752 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 684 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
753 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n"); 685 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
754 return -EINVAL; 686 return -EINVAL;
755 } 687 }
756 if (buf->memory != V4L2_MEMORY_MMAP) { 688 index = buf->index;
757 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n"); 689 if (index < 0 || index >= pwc_mbufs) {
758 return -EINVAL; 690 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
759 } 691 return -EINVAL;
760 index = buf->index; 692 }
761 if (index < 0 || index >= pwc_mbufs) {
762 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
763 return -EINVAL;
764 }
765 693
766 memset(buf, 0, sizeof(struct v4l2_buffer)); 694 buf->m.offset = index * pdev->len_per_image;
767 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 695 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
768 buf->index = index; 696 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
769 buf->m.offset = index * pdev->len_per_image; 697 else
770 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) 698 buf->bytesused = pdev->view.size;
771 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); 699 buf->field = V4L2_FIELD_NONE;
772 else 700 buf->memory = V4L2_MEMORY_MMAP;
773 buf->bytesused = pdev->view.size; 701 /*buf->flags = V4L2_BUF_FLAG_MAPPED;*/
774 buf->field = V4L2_FIELD_NONE; 702 buf->length = pdev->len_per_image;
775 buf->memory = V4L2_MEMORY_MMAP;
776 //buf->flags = V4L2_BUF_FLAG_MAPPED;
777 buf->length = pdev->len_per_image;
778
779 PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
780 PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
781 PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
782 703
783 return 0; 704 PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n", buf->index);
784 } 705 PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n", buf->m.offset);
706 PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n", buf->bytesused);
785 707
786 case VIDIOC_QBUF: 708 return 0;
787 { 709}
788 struct v4l2_buffer *buf = arg;
789 710
790 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index); 711static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
791 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 712{
792 return -EINVAL; 713 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n", buf->index);
793 if (buf->memory != V4L2_MEMORY_MMAP) 714 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
794 return -EINVAL; 715 return -EINVAL;
795 if (buf->index >= pwc_mbufs) 716 if (buf->memory != V4L2_MEMORY_MMAP)
796 return -EINVAL; 717 return -EINVAL;
718 if (buf->index >= pwc_mbufs)
719 return -EINVAL;
797 720
798 buf->flags |= V4L2_BUF_FLAG_QUEUED; 721 buf->flags |= V4L2_BUF_FLAG_QUEUED;
799 buf->flags &= ~V4L2_BUF_FLAG_DONE; 722 buf->flags &= ~V4L2_BUF_FLAG_DONE;
800 723
801 return 0; 724 return 0;
802 } 725}
803 726
804 case VIDIOC_DQBUF: 727static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
805 { 728{
806 struct v4l2_buffer *buf = arg; 729 DECLARE_WAITQUEUE(wait, current);
807 int ret; 730 struct pwc_device *pdev = video_drvdata(file);
731 int ret;
808 732
809 PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n"); 733 PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
810 734
811 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 735 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
812 return -EINVAL; 736 return -EINVAL;
813 737
814 /* Add ourselves to the frame wait-queue. 738 add_wait_queue(&pdev->frameq, &wait);
815 739 while (pdev->full_frames == NULL) {
816 FIXME: needs auditing for safety. 740 if (pdev->error_status) {
817 QUESTION: In what respect? I think that using the 741 remove_wait_queue(&pdev->frameq, &wait);
818 frameq is safe now. 742 set_current_state(TASK_RUNNING);
819 */ 743 return -pdev->error_status;
820 add_wait_queue(&pdev->frameq, &wait); 744 }
821 while (pdev->full_frames == NULL) {
822 if (pdev->error_status) {
823 remove_wait_queue(&pdev->frameq, &wait);
824 set_current_state(TASK_RUNNING);
825 return -pdev->error_status;
826 }
827 745
828 if (signal_pending(current)) { 746 if (signal_pending(current)) {
829 remove_wait_queue(&pdev->frameq, &wait);
830 set_current_state(TASK_RUNNING);
831 return -ERESTARTSYS;
832 }
833 mutex_unlock(&pdev->modlock);
834 schedule();
835 set_current_state(TASK_INTERRUPTIBLE);
836 mutex_lock(&pdev->modlock);
837 }
838 remove_wait_queue(&pdev->frameq, &wait); 747 remove_wait_queue(&pdev->frameq, &wait);
839 set_current_state(TASK_RUNNING); 748 set_current_state(TASK_RUNNING);
749 return -ERESTARTSYS;
750 }
751 mutex_unlock(&pdev->modlock);
752 schedule();
753 set_current_state(TASK_INTERRUPTIBLE);
754 mutex_lock(&pdev->modlock);
755 }
756 remove_wait_queue(&pdev->frameq, &wait);
757 set_current_state(TASK_RUNNING);
840 758
841 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n"); 759 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
842 /* Decompress data in pdev->images[pdev->fill_image] */ 760 /* Decompress data in pdev->images[pdev->fill_image] */
843 ret = pwc_handle_frame(pdev); 761 ret = pwc_handle_frame(pdev);
844 if (ret) 762 if (ret)
845 return -EFAULT; 763 return -EFAULT;
846 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n"); 764 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
847 765
848 buf->index = pdev->fill_image; 766 buf->index = pdev->fill_image;
849 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) 767 if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
850 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); 768 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
851 else 769 else
852 buf->bytesused = pdev->view.size; 770 buf->bytesused = pdev->view.size;
853 buf->flags = V4L2_BUF_FLAG_MAPPED; 771 buf->flags = V4L2_BUF_FLAG_MAPPED;
854 buf->field = V4L2_FIELD_NONE; 772 buf->field = V4L2_FIELD_NONE;
855 do_gettimeofday(&buf->timestamp); 773 do_gettimeofday(&buf->timestamp);
856 buf->sequence = 0; 774 buf->sequence = 0;
857 buf->memory = V4L2_MEMORY_MMAP; 775 buf->memory = V4L2_MEMORY_MMAP;
858 buf->m.offset = pdev->fill_image * pdev->len_per_image; 776 buf->m.offset = pdev->fill_image * pdev->len_per_image;
859 buf->length = pdev->len_per_image; 777 buf->length = pdev->len_per_image;
860 pwc_next_image(pdev); 778 pwc_next_image(pdev);
861 779
862 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index); 780 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n", buf->index);
863 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length); 781 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n", buf->length);
864 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset); 782 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n", buf->m.offset);
865 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused); 783 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n", buf->bytesused);
866 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n"); 784 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
867 return 0; 785 return 0;
868 786
869 } 787}
870 788
871 case VIDIOC_STREAMON: 789static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
872 { 790{
873 return pwc_isoc_init(pdev); 791 struct pwc_device *pdev = video_drvdata(file);
874 }
875 792
876 case VIDIOC_STREAMOFF: 793 return pwc_isoc_init(pdev);
877 { 794}
878 pwc_isoc_cleanup(pdev);
879 return 0;
880 }
881 795
882 case VIDIOC_ENUM_FRAMESIZES: 796static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
883 { 797{
884 struct v4l2_frmsizeenum *fsize = arg; 798 struct pwc_device *pdev = video_drvdata(file);
885 unsigned int i = 0, index = fsize->index;
886
887 if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
888 for (i = 0; i < PSZ_MAX; i++) {
889 if (pdev->image_mask & (1UL << i)) {
890 if (!index--) {
891 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
892 fsize->discrete.width = pwc_image_sizes[i].x;
893 fsize->discrete.height = pwc_image_sizes[i].y;
894 return 0;
895 }
896 }
897 }
898 } else if (fsize->index == 0 &&
899 ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
900 (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
901
902 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
903 fsize->discrete.width = pdev->abs_max.x;
904 fsize->discrete.height = pdev->abs_max.y;
905 return 0;
906 }
907 return -EINVAL;
908 }
909 799
910 case VIDIOC_ENUM_FRAMEINTERVALS: 800 pwc_isoc_cleanup(pdev);
911 { 801 return 0;
912 struct v4l2_frmivalenum *fival = arg; 802}
913 int size = -1; 803
914 unsigned int i; 804static int pwc_enum_framesizes(struct file *file, void *fh,
915 805 struct v4l2_frmsizeenum *fsize)
916 for (i = 0; i < PSZ_MAX; i++) { 806{
917 if (pwc_image_sizes[i].x == fival->width && 807 struct pwc_device *pdev = video_drvdata(file);
918 pwc_image_sizes[i].y == fival->height) { 808 unsigned int i = 0, index = fsize->index;
919 size = i; 809
920 break; 810 if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
811 for (i = 0; i < PSZ_MAX; i++) {
812 if (pdev->image_mask & (1UL << i)) {
813 if (!index--) {
814 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
815 fsize->discrete.width = pwc_image_sizes[i].x;
816 fsize->discrete.height = pwc_image_sizes[i].y;
817 return 0;
921 } 818 }
922 } 819 }
820 }
821 } else if (fsize->index == 0 &&
822 ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
823 (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
824
825 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
826 fsize->discrete.width = pdev->abs_max.x;
827 fsize->discrete.height = pdev->abs_max.y;
828 return 0;
829 }
830 return -EINVAL;
831}
923 832
924 /* TODO: Support raw format */ 833static int pwc_enum_frameintervals(struct file *file, void *fh,
925 if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420) { 834 struct v4l2_frmivalenum *fival)
926 return -EINVAL; 835{
927 } 836 struct pwc_device *pdev = video_drvdata(file);
837 int size = -1;
838 unsigned int i;
839
840 for (i = 0; i < PSZ_MAX; i++) {
841 if (pwc_image_sizes[i].x == fival->width &&
842 pwc_image_sizes[i].y == fival->height) {
843 size = i;
844 break;
845 }
846 }
928 847
929 i = pwc_get_fps(pdev, fival->index, size); 848 /* TODO: Support raw format */
930 if (!i) 849 if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
931 return -EINVAL; 850 return -EINVAL;
932 851
933 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; 852 i = pwc_get_fps(pdev, fival->index, size);
934 fival->discrete.numerator = 1; 853 if (!i)
935 fival->discrete.denominator = i; 854 return -EINVAL;
936 855
937 return 0; 856 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
938 } 857 fival->discrete.numerator = 1;
858 fival->discrete.denominator = i;
939 859
940 default:
941 return pwc_ioctl(pdev, cmd, arg);
942 } /* ..switch */
943 return 0; 860 return 0;
944} 861}
945 862
863static long pwc_default(struct file *file, void *fh, int cmd, void *arg)
864{
865 struct pwc_device *pdev = video_drvdata(file);
866
867 return pwc_ioctl(pdev, cmd, arg);
868}
869
870const struct v4l2_ioctl_ops pwc_ioctl_ops = {
871 .vidioc_querycap = pwc_querycap,
872 .vidioc_enum_input = pwc_enum_input,
873 .vidioc_g_input = pwc_g_input,
874 .vidioc_s_input = pwc_s_input,
875 .vidioc_enum_fmt_vid_cap = pwc_enum_fmt_vid_cap,
876 .vidioc_g_fmt_vid_cap = pwc_g_fmt_vid_cap,
877 .vidioc_s_fmt_vid_cap = pwc_s_fmt_vid_cap,
878 .vidioc_try_fmt_vid_cap = pwc_try_fmt_vid_cap,
879 .vidioc_queryctrl = pwc_queryctrl,
880 .vidioc_g_ctrl = pwc_g_ctrl,
881 .vidioc_s_ctrl = pwc_s_ctrl,
882 .vidioc_reqbufs = pwc_reqbufs,
883 .vidioc_querybuf = pwc_querybuf,
884 .vidioc_qbuf = pwc_qbuf,
885 .vidioc_dqbuf = pwc_dqbuf,
886 .vidioc_streamon = pwc_streamon,
887 .vidioc_streamoff = pwc_streamoff,
888 .vidioc_enum_framesizes = pwc_enum_framesizes,
889 .vidioc_enum_frameintervals = pwc_enum_frameintervals,
890 .vidioc_default = pwc_default,
891};
892
893
946/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ 894/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 16bbc6df9b07..e947766337d6 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -339,8 +339,7 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power);
339/* Private ioctl()s; see pwc-ioctl.h */ 339/* Private ioctl()s; see pwc-ioctl.h */
340extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); 340extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
341 341
342/** Functions in pwc-v4l.c */ 342extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
343extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
344 343
345/** pwc-uncompress.c */ 344/** pwc-uncompress.c */
346/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */ 345/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */