diff options
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 297 |
1 files changed, 100 insertions, 197 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 01ff643e682d..943d37ad0d33 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -134,7 +134,6 @@ static int default_fps = 10; | |||
134 | #endif | 134 | #endif |
135 | static int power_save = -1; | 135 | static int power_save = -1; |
136 | static int led_on = 100, led_off; /* defaults to LED that is on while in use */ | 136 | static int led_on = 100, led_off; /* defaults to LED that is on while in use */ |
137 | static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ | ||
138 | static struct { | 137 | static struct { |
139 | int type; | 138 | int type; |
140 | char serial_number[30]; | 139 | char serial_number[30]; |
@@ -144,17 +143,15 @@ static struct { | |||
144 | 143 | ||
145 | /***/ | 144 | /***/ |
146 | 145 | ||
147 | static int pwc_video_open(struct file *file); | ||
148 | static int pwc_video_close(struct file *file); | 146 | static int pwc_video_close(struct file *file); |
149 | static ssize_t pwc_video_read(struct file *file, char __user *buf, | 147 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
150 | size_t count, loff_t *ppos); | 148 | size_t count, loff_t *ppos); |
151 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); | 149 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); |
152 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); | 150 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); |
153 | static void pwc_video_release(struct video_device *vfd); | ||
154 | 151 | ||
155 | static const struct v4l2_file_operations pwc_fops = { | 152 | static const struct v4l2_file_operations pwc_fops = { |
156 | .owner = THIS_MODULE, | 153 | .owner = THIS_MODULE, |
157 | .open = pwc_video_open, | 154 | .open = v4l2_fh_open, |
158 | .release = pwc_video_close, | 155 | .release = pwc_video_close, |
159 | .read = pwc_video_read, | 156 | .read = pwc_video_read, |
160 | .poll = pwc_video_poll, | 157 | .poll = pwc_video_poll, |
@@ -163,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = { | |||
163 | }; | 160 | }; |
164 | static struct video_device pwc_template = { | 161 | static struct video_device pwc_template = { |
165 | .name = "Philips Webcam", /* Filled in later */ | 162 | .name = "Philips Webcam", /* Filled in later */ |
166 | .release = pwc_video_release, | 163 | .release = video_device_release_empty, |
167 | .fops = &pwc_fops, | 164 | .fops = &pwc_fops, |
168 | .ioctl_ops = &pwc_ioctl_ops, | 165 | .ioctl_ops = &pwc_ioctl_ops, |
169 | }; | 166 | }; |
@@ -191,7 +188,6 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down) | |||
191 | { | 188 | { |
192 | if (down) { | 189 | if (down) { |
193 | PWC_TRACE("Snapshot button pressed.\n"); | 190 | PWC_TRACE("Snapshot button pressed.\n"); |
194 | pdev->snapshot_button_status = 1; | ||
195 | } else { | 191 | } else { |
196 | PWC_TRACE("Snapshot button released.\n"); | 192 | PWC_TRACE("Snapshot button released.\n"); |
197 | } | 193 | } |
@@ -375,6 +371,7 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
375 | int i, j, ret; | 371 | int i, j, ret; |
376 | struct usb_interface *intf; | 372 | struct usb_interface *intf; |
377 | struct usb_host_interface *idesc = NULL; | 373 | struct usb_host_interface *idesc = NULL; |
374 | int compression = 0; /* 0..3 = uncompressed..high */ | ||
378 | 375 | ||
379 | if (pdev->iso_init) | 376 | if (pdev->iso_init) |
380 | return 0; | 377 | return 0; |
@@ -386,6 +383,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
386 | pdev->visoc_errors = 0; | 383 | pdev->visoc_errors = 0; |
387 | udev = pdev->udev; | 384 | udev = pdev->udev; |
388 | 385 | ||
386 | retry: | ||
387 | /* We first try with low compression and then retry with a higher | ||
388 | compression setting if there is not enough bandwidth. */ | ||
389 | ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, | ||
390 | pdev->vframes, &compression); | ||
391 | |||
389 | /* Get the current alternate interface, adjust packet size */ | 392 | /* Get the current alternate interface, adjust packet size */ |
390 | intf = usb_ifnum_to_if(udev, 0); | 393 | intf = usb_ifnum_to_if(udev, 0); |
391 | if (intf) | 394 | if (intf) |
@@ -408,9 +411,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
408 | } | 411 | } |
409 | 412 | ||
410 | /* Set alternate interface */ | 413 | /* Set alternate interface */ |
411 | ret = 0; | ||
412 | PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); | 414 | PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); |
413 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); | 415 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); |
416 | if (ret == -ENOSPC && compression < 3) { | ||
417 | compression++; | ||
418 | goto retry; | ||
419 | } | ||
414 | if (ret < 0) | 420 | if (ret < 0) |
415 | return ret; | 421 | return ret; |
416 | 422 | ||
@@ -454,6 +460,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
454 | /* link */ | 460 | /* link */ |
455 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 461 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
456 | ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL); | 462 | ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL); |
463 | if (ret == -ENOSPC && compression < 3) { | ||
464 | compression++; | ||
465 | pdev->iso_init = 1; | ||
466 | pwc_isoc_cleanup(pdev); | ||
467 | goto retry; | ||
468 | } | ||
457 | if (ret) { | 469 | if (ret) { |
458 | PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); | 470 | PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); |
459 | pdev->iso_init = 1; | 471 | pdev->iso_init = 1; |
@@ -517,12 +529,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) | |||
517 | PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); | 529 | PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); |
518 | } | 530 | } |
519 | 531 | ||
520 | /* | ||
521 | * Release all queued buffers, no need to take queued_bufs_lock, since all | ||
522 | * iso urbs have been killed when we're called so pwc_isoc_handler won't run. | ||
523 | */ | ||
524 | static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) | 532 | static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) |
525 | { | 533 | { |
534 | unsigned long flags = 0; | ||
535 | |||
536 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); | ||
526 | while (!list_empty(&pdev->queued_bufs)) { | 537 | while (!list_empty(&pdev->queued_bufs)) { |
527 | struct pwc_frame_buf *buf; | 538 | struct pwc_frame_buf *buf; |
528 | 539 | ||
@@ -531,84 +542,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) | |||
531 | list_del(&buf->list); | 542 | list_del(&buf->list); |
532 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | 543 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
533 | } | 544 | } |
534 | } | 545 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); |
535 | |||
536 | /********* | ||
537 | * sysfs | ||
538 | *********/ | ||
539 | static struct pwc_device *cd_to_pwc(struct device *cd) | ||
540 | { | ||
541 | struct video_device *vdev = to_video_device(cd); | ||
542 | return video_get_drvdata(vdev); | ||
543 | } | ||
544 | |||
545 | static ssize_t show_pan_tilt(struct device *class_dev, | ||
546 | struct device_attribute *attr, char *buf) | ||
547 | { | ||
548 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
549 | return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); | ||
550 | } | ||
551 | |||
552 | static ssize_t store_pan_tilt(struct device *class_dev, | ||
553 | struct device_attribute *attr, | ||
554 | const char *buf, size_t count) | ||
555 | { | ||
556 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
557 | int pan, tilt; | ||
558 | int ret = -EINVAL; | ||
559 | |||
560 | if (strncmp(buf, "reset", 5) == 0) | ||
561 | ret = pwc_mpt_reset(pdev, 0x3); | ||
562 | |||
563 | else if (sscanf(buf, "%d %d", &pan, &tilt) > 0) | ||
564 | ret = pwc_mpt_set_angle(pdev, pan, tilt); | ||
565 | |||
566 | if (ret < 0) | ||
567 | return ret; | ||
568 | return strlen(buf); | ||
569 | } | ||
570 | static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, | ||
571 | store_pan_tilt); | ||
572 | |||
573 | static ssize_t show_snapshot_button_status(struct device *class_dev, | ||
574 | struct device_attribute *attr, char *buf) | ||
575 | { | ||
576 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
577 | int status = pdev->snapshot_button_status; | ||
578 | pdev->snapshot_button_status = 0; | ||
579 | return sprintf(buf, "%d\n", status); | ||
580 | } | ||
581 | |||
582 | static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, | ||
583 | NULL); | ||
584 | |||
585 | static int pwc_create_sysfs_files(struct pwc_device *pdev) | ||
586 | { | ||
587 | int rc; | ||
588 | |||
589 | rc = device_create_file(&pdev->vdev.dev, &dev_attr_button); | ||
590 | if (rc) | ||
591 | goto err; | ||
592 | if (pdev->features & FEATURE_MOTOR_PANTILT) { | ||
593 | rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt); | ||
594 | if (rc) | ||
595 | goto err_button; | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | |||
600 | err_button: | ||
601 | device_remove_file(&pdev->vdev.dev, &dev_attr_button); | ||
602 | err: | ||
603 | PWC_ERROR("Could not create sysfs files.\n"); | ||
604 | return rc; | ||
605 | } | ||
606 | |||
607 | static void pwc_remove_sysfs_files(struct pwc_device *pdev) | ||
608 | { | ||
609 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
610 | device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt); | ||
611 | device_remove_file(&pdev->vdev.dev, &dev_attr_button); | ||
612 | } | 546 | } |
613 | 547 | ||
614 | #ifdef CONFIG_USB_PWC_DEBUG | 548 | #ifdef CONFIG_USB_PWC_DEBUG |
@@ -644,25 +578,25 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type) | |||
644 | /***************************************************************************/ | 578 | /***************************************************************************/ |
645 | /* Video4Linux functions */ | 579 | /* Video4Linux functions */ |
646 | 580 | ||
647 | static int pwc_video_open(struct file *file) | 581 | int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file) |
648 | { | 582 | { |
649 | struct video_device *vdev = video_devdata(file); | 583 | int r = 0; |
650 | struct pwc_device *pdev; | ||
651 | |||
652 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); | ||
653 | 584 | ||
654 | pdev = video_get_drvdata(vdev); | 585 | mutex_lock(&pdev->capt_file_lock); |
655 | if (!pdev->udev) | 586 | if (pdev->capt_file != NULL && |
656 | return -ENODEV; | 587 | pdev->capt_file != file) { |
657 | 588 | r = -EBUSY; | |
658 | file->private_data = vdev; | 589 | goto leave; |
659 | PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); | 590 | } |
660 | return 0; | 591 | pdev->capt_file = file; |
592 | leave: | ||
593 | mutex_unlock(&pdev->capt_file_lock); | ||
594 | return r; | ||
661 | } | 595 | } |
662 | 596 | ||
663 | static void pwc_video_release(struct video_device *vfd) | 597 | static void pwc_video_release(struct v4l2_device *v) |
664 | { | 598 | { |
665 | struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev); | 599 | struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); |
666 | int hint; | 600 | int hint; |
667 | 601 | ||
668 | /* search device_hint[] table if we occupy a slot, by any chance */ | 602 | /* search device_hint[] table if we occupy a slot, by any chance */ |
@@ -685,44 +619,33 @@ static void pwc_video_release(struct video_device *vfd) | |||
685 | 619 | ||
686 | static int pwc_video_close(struct file *file) | 620 | static int pwc_video_close(struct file *file) |
687 | { | 621 | { |
688 | struct video_device *vdev = file->private_data; | 622 | struct pwc_device *pdev = video_drvdata(file); |
689 | struct pwc_device *pdev; | ||
690 | |||
691 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | ||
692 | 623 | ||
693 | pdev = video_get_drvdata(vdev); | ||
694 | if (pdev->capt_file == file) { | 624 | if (pdev->capt_file == file) { |
695 | vb2_queue_release(&pdev->vb_queue); | 625 | vb2_queue_release(&pdev->vb_queue); |
696 | pdev->capt_file = NULL; | 626 | pdev->capt_file = NULL; |
697 | } | 627 | } |
698 | 628 | return v4l2_fh_release(file); | |
699 | PWC_DEBUG_OPEN("<< video_close()\n"); | ||
700 | return 0; | ||
701 | } | 629 | } |
702 | 630 | ||
703 | static ssize_t pwc_video_read(struct file *file, char __user *buf, | 631 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
704 | size_t count, loff_t *ppos) | 632 | size_t count, loff_t *ppos) |
705 | { | 633 | { |
706 | struct video_device *vdev = file->private_data; | 634 | struct pwc_device *pdev = video_drvdata(file); |
707 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
708 | 635 | ||
709 | if (!pdev->udev) | 636 | if (!pdev->udev) |
710 | return -ENODEV; | 637 | return -ENODEV; |
711 | 638 | ||
712 | if (pdev->capt_file != NULL && | 639 | if (pwc_test_n_set_capt_file(pdev, file)) |
713 | pdev->capt_file != file) | ||
714 | return -EBUSY; | 640 | return -EBUSY; |
715 | 641 | ||
716 | pdev->capt_file = file; | ||
717 | |||
718 | return vb2_read(&pdev->vb_queue, buf, count, ppos, | 642 | return vb2_read(&pdev->vb_queue, buf, count, ppos, |
719 | file->f_flags & O_NONBLOCK); | 643 | file->f_flags & O_NONBLOCK); |
720 | } | 644 | } |
721 | 645 | ||
722 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | 646 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) |
723 | { | 647 | { |
724 | struct video_device *vdev = file->private_data; | 648 | struct pwc_device *pdev = video_drvdata(file); |
725 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
726 | 649 | ||
727 | if (!pdev->udev) | 650 | if (!pdev->udev) |
728 | return POLL_ERR; | 651 | return POLL_ERR; |
@@ -732,8 +655,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
732 | 655 | ||
733 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | 656 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) |
734 | { | 657 | { |
735 | struct video_device *vdev = file->private_data; | 658 | struct pwc_device *pdev = video_drvdata(file); |
736 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
737 | 659 | ||
738 | if (pdev->capt_file != file) | 660 | if (pdev->capt_file != file) |
739 | return -EBUSY; | 661 | return -EBUSY; |
@@ -749,6 +671,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
749 | unsigned int sizes[], void *alloc_ctxs[]) | 671 | unsigned int sizes[], void *alloc_ctxs[]) |
750 | { | 672 | { |
751 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 673 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
674 | int size; | ||
752 | 675 | ||
753 | if (*nbuffers < MIN_FRAMES) | 676 | if (*nbuffers < MIN_FRAMES) |
754 | *nbuffers = MIN_FRAMES; | 677 | *nbuffers = MIN_FRAMES; |
@@ -757,7 +680,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
757 | 680 | ||
758 | *nplanes = 1; | 681 | *nplanes = 1; |
759 | 682 | ||
760 | sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2); | 683 | size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT); |
684 | sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] * | ||
685 | pwc_image_sizes[size][1] * 3 / 2); | ||
761 | 686 | ||
762 | return 0; | 687 | return 0; |
763 | } | 688 | } |
@@ -812,56 +737,59 @@ static void buffer_queue(struct vb2_buffer *vb) | |||
812 | unsigned long flags = 0; | 737 | unsigned long flags = 0; |
813 | 738 | ||
814 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); | 739 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); |
815 | list_add_tail(&buf->list, &pdev->queued_bufs); | 740 | /* Check the device has not disconnected between prep and queuing */ |
741 | if (pdev->udev) | ||
742 | list_add_tail(&buf->list, &pdev->queued_bufs); | ||
743 | else | ||
744 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
816 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); | 745 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); |
817 | } | 746 | } |
818 | 747 | ||
819 | static int start_streaming(struct vb2_queue *vq, unsigned int count) | 748 | static int start_streaming(struct vb2_queue *vq, unsigned int count) |
820 | { | 749 | { |
821 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 750 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
751 | int r; | ||
822 | 752 | ||
823 | if (!pdev->udev) | 753 | mutex_lock(&pdev->udevlock); |
824 | return -ENODEV; | 754 | if (!pdev->udev) { |
755 | r = -ENODEV; | ||
756 | goto leave; | ||
757 | } | ||
825 | 758 | ||
826 | /* Turn on camera and set LEDS on */ | 759 | /* Turn on camera and set LEDS on */ |
827 | pwc_camera_power(pdev, 1); | 760 | pwc_camera_power(pdev, 1); |
828 | if (pdev->power_save) { | ||
829 | /* Restore video mode */ | ||
830 | pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, | ||
831 | pdev->vframes, pdev->vcompression, | ||
832 | pdev->vsnapshot); | ||
833 | } | ||
834 | pwc_set_leds(pdev, led_on, led_off); | 761 | pwc_set_leds(pdev, led_on, led_off); |
835 | 762 | ||
836 | return pwc_isoc_init(pdev); | 763 | r = pwc_isoc_init(pdev); |
764 | if (r) { | ||
765 | /* If we failed turn camera and LEDS back off */ | ||
766 | pwc_set_leds(pdev, 0, 0); | ||
767 | pwc_camera_power(pdev, 0); | ||
768 | /* And cleanup any queued bufs!! */ | ||
769 | pwc_cleanup_queued_bufs(pdev); | ||
770 | } | ||
771 | leave: | ||
772 | mutex_unlock(&pdev->udevlock); | ||
773 | return r; | ||
837 | } | 774 | } |
838 | 775 | ||
839 | static int stop_streaming(struct vb2_queue *vq) | 776 | static int stop_streaming(struct vb2_queue *vq) |
840 | { | 777 | { |
841 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 778 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
842 | 779 | ||
780 | mutex_lock(&pdev->udevlock); | ||
843 | if (pdev->udev) { | 781 | if (pdev->udev) { |
844 | pwc_set_leds(pdev, 0, 0); | 782 | pwc_set_leds(pdev, 0, 0); |
845 | pwc_camera_power(pdev, 0); | 783 | pwc_camera_power(pdev, 0); |
846 | pwc_isoc_cleanup(pdev); | 784 | pwc_isoc_cleanup(pdev); |
847 | } | 785 | } |
786 | mutex_unlock(&pdev->udevlock); | ||
787 | |||
848 | pwc_cleanup_queued_bufs(pdev); | 788 | pwc_cleanup_queued_bufs(pdev); |
849 | 789 | ||
850 | return 0; | 790 | return 0; |
851 | } | 791 | } |
852 | 792 | ||
853 | static void pwc_lock(struct vb2_queue *vq) | ||
854 | { | ||
855 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | ||
856 | mutex_lock(&pdev->modlock); | ||
857 | } | ||
858 | |||
859 | static void pwc_unlock(struct vb2_queue *vq) | ||
860 | { | ||
861 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | ||
862 | mutex_unlock(&pdev->modlock); | ||
863 | } | ||
864 | |||
865 | static struct vb2_ops pwc_vb_queue_ops = { | 793 | static struct vb2_ops pwc_vb_queue_ops = { |
866 | .queue_setup = queue_setup, | 794 | .queue_setup = queue_setup, |
867 | .buf_init = buffer_init, | 795 | .buf_init = buffer_init, |
@@ -871,8 +799,6 @@ static struct vb2_ops pwc_vb_queue_ops = { | |||
871 | .buf_queue = buffer_queue, | 799 | .buf_queue = buffer_queue, |
872 | .start_streaming = start_streaming, | 800 | .start_streaming = start_streaming, |
873 | .stop_streaming = stop_streaming, | 801 | .stop_streaming = stop_streaming, |
874 | .wait_prepare = pwc_unlock, | ||
875 | .wait_finish = pwc_lock, | ||
876 | }; | 802 | }; |
877 | 803 | ||
878 | /***************************************************************************/ | 804 | /***************************************************************************/ |
@@ -889,6 +815,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
889 | int vendor_id, product_id, type_id; | 815 | int vendor_id, product_id, type_id; |
890 | int hint, rc; | 816 | int hint, rc; |
891 | int features = 0; | 817 | int features = 0; |
818 | int compression = 0; | ||
892 | int video_nr = -1; /* default: use next available device */ | 819 | int video_nr = -1; /* default: use next available device */ |
893 | int my_power_save = power_save; | 820 | int my_power_save = power_save; |
894 | char serial_number[30], *name; | 821 | char serial_number[30], *name; |
@@ -1150,27 +1077,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1150 | } | 1077 | } |
1151 | pdev->type = type_id; | 1078 | pdev->type = type_id; |
1152 | pdev->vframes = default_fps; | 1079 | pdev->vframes = default_fps; |
1153 | strcpy(pdev->serial, serial_number); | ||
1154 | pdev->features = features; | 1080 | pdev->features = features; |
1155 | if (vendor_id == 0x046D && product_id == 0x08B5) { | ||
1156 | /* Logitech QuickCam Orbit | ||
1157 | The ranges have been determined experimentally; they may differ from cam to cam. | ||
1158 | Also, the exact ranges left-right and up-down are different for my cam | ||
1159 | */ | ||
1160 | pdev->angle_range.pan_min = -7000; | ||
1161 | pdev->angle_range.pan_max = 7000; | ||
1162 | pdev->angle_range.tilt_min = -3000; | ||
1163 | pdev->angle_range.tilt_max = 2500; | ||
1164 | } | ||
1165 | pwc_construct(pdev); /* set min/max sizes correct */ | 1081 | pwc_construct(pdev); /* set min/max sizes correct */ |
1166 | 1082 | ||
1167 | mutex_init(&pdev->modlock); | 1083 | mutex_init(&pdev->capt_file_lock); |
1168 | mutex_init(&pdev->udevlock); | 1084 | mutex_init(&pdev->udevlock); |
1169 | spin_lock_init(&pdev->queued_bufs_lock); | 1085 | spin_lock_init(&pdev->queued_bufs_lock); |
1170 | INIT_LIST_HEAD(&pdev->queued_bufs); | 1086 | INIT_LIST_HEAD(&pdev->queued_bufs); |
1171 | 1087 | ||
1172 | pdev->udev = udev; | 1088 | pdev->udev = udev; |
1173 | pdev->vcompression = pwc_preferred_compression; | ||
1174 | pdev->power_save = my_power_save; | 1089 | pdev->power_save = my_power_save; |
1175 | 1090 | ||
1176 | /* Init videobuf2 queue structure */ | 1091 | /* Init videobuf2 queue structure */ |
@@ -1185,9 +1100,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1185 | 1100 | ||
1186 | /* Init video_device structure */ | 1101 | /* Init video_device structure */ |
1187 | memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); | 1102 | memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); |
1188 | pdev->vdev.parent = &intf->dev; | ||
1189 | pdev->vdev.lock = &pdev->modlock; | ||
1190 | strcpy(pdev->vdev.name, name); | 1103 | strcpy(pdev->vdev.name, name); |
1104 | set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags); | ||
1191 | video_set_drvdata(&pdev->vdev, pdev); | 1105 | video_set_drvdata(&pdev->vdev, pdev); |
1192 | 1106 | ||
1193 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); | 1107 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); |
@@ -1211,9 +1125,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1211 | if (hint < MAX_DEV_HINTS) | 1125 | if (hint < MAX_DEV_HINTS) |
1212 | device_hint[hint].pdev = pdev; | 1126 | device_hint[hint].pdev = pdev; |
1213 | 1127 | ||
1214 | PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); | ||
1215 | usb_set_intfdata(intf, pdev); | ||
1216 | |||
1217 | #ifdef CONFIG_USB_PWC_DEBUG | 1128 | #ifdef CONFIG_USB_PWC_DEBUG |
1218 | /* Query sensor type */ | 1129 | /* Query sensor type */ |
1219 | if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { | 1130 | if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { |
@@ -1227,8 +1138,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1227 | pwc_set_leds(pdev, 0, 0); | 1138 | pwc_set_leds(pdev, 0, 0); |
1228 | 1139 | ||
1229 | /* Setup intial videomode */ | 1140 | /* Setup intial videomode */ |
1230 | rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y, | 1141 | rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes, |
1231 | pdev->vframes, pdev->vcompression, 0); | 1142 | &compression); |
1232 | if (rc) | 1143 | if (rc) |
1233 | goto err_free_mem; | 1144 | goto err_free_mem; |
1234 | 1145 | ||
@@ -1239,20 +1150,25 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1239 | goto err_free_mem; | 1150 | goto err_free_mem; |
1240 | } | 1151 | } |
1241 | 1152 | ||
1242 | pdev->vdev.ctrl_handler = &pdev->ctrl_handler; | ||
1243 | |||
1244 | /* And powerdown the camera until streaming starts */ | 1153 | /* And powerdown the camera until streaming starts */ |
1245 | pwc_camera_power(pdev, 0); | 1154 | pwc_camera_power(pdev, 0); |
1246 | 1155 | ||
1156 | /* Register the v4l2_device structure */ | ||
1157 | pdev->v4l2_dev.release = pwc_video_release; | ||
1158 | rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev); | ||
1159 | if (rc) { | ||
1160 | PWC_ERROR("Failed to register v4l2-device (%d).\n", rc); | ||
1161 | goto err_free_controls; | ||
1162 | } | ||
1163 | |||
1164 | pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; | ||
1165 | pdev->vdev.v4l2_dev = &pdev->v4l2_dev; | ||
1166 | |||
1247 | rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); | 1167 | rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); |
1248 | if (rc < 0) { | 1168 | if (rc < 0) { |
1249 | PWC_ERROR("Failed to register as video device (%d).\n", rc); | 1169 | PWC_ERROR("Failed to register as video device (%d).\n", rc); |
1250 | goto err_free_controls; | 1170 | goto err_unregister_v4l2_dev; |
1251 | } | 1171 | } |
1252 | rc = pwc_create_sysfs_files(pdev); | ||
1253 | if (rc) | ||
1254 | goto err_video_unreg; | ||
1255 | |||
1256 | PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); | 1172 | PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); |
1257 | 1173 | ||
1258 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 1174 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
@@ -1261,7 +1177,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1261 | if (!pdev->button_dev) { | 1177 | if (!pdev->button_dev) { |
1262 | PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); | 1178 | PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); |
1263 | rc = -ENOMEM; | 1179 | rc = -ENOMEM; |
1264 | pwc_remove_sysfs_files(pdev); | ||
1265 | goto err_video_unreg; | 1180 | goto err_video_unreg; |
1266 | } | 1181 | } |
1267 | 1182 | ||
@@ -1279,7 +1194,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1279 | if (rc) { | 1194 | if (rc) { |
1280 | input_free_device(pdev->button_dev); | 1195 | input_free_device(pdev->button_dev); |
1281 | pdev->button_dev = NULL; | 1196 | pdev->button_dev = NULL; |
1282 | pwc_remove_sysfs_files(pdev); | ||
1283 | goto err_video_unreg; | 1197 | goto err_video_unreg; |
1284 | } | 1198 | } |
1285 | #endif | 1199 | #endif |
@@ -1287,13 +1201,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1287 | return 0; | 1201 | return 0; |
1288 | 1202 | ||
1289 | err_video_unreg: | 1203 | err_video_unreg: |
1290 | if (hint < MAX_DEV_HINTS) | ||
1291 | device_hint[hint].pdev = NULL; | ||
1292 | video_unregister_device(&pdev->vdev); | 1204 | video_unregister_device(&pdev->vdev); |
1205 | err_unregister_v4l2_dev: | ||
1206 | v4l2_device_unregister(&pdev->v4l2_dev); | ||
1293 | err_free_controls: | 1207 | err_free_controls: |
1294 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); | 1208 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); |
1295 | err_free_mem: | 1209 | err_free_mem: |
1296 | usb_set_intfdata(intf, NULL); | 1210 | if (hint < MAX_DEV_HINTS) |
1211 | device_hint[hint].pdev = NULL; | ||
1297 | kfree(pdev); | 1212 | kfree(pdev); |
1298 | return rc; | 1213 | return rc; |
1299 | } | 1214 | } |
@@ -1301,27 +1216,26 @@ err_free_mem: | |||
1301 | /* The user yanked out the cable... */ | 1216 | /* The user yanked out the cable... */ |
1302 | static void usb_pwc_disconnect(struct usb_interface *intf) | 1217 | static void usb_pwc_disconnect(struct usb_interface *intf) |
1303 | { | 1218 | { |
1304 | struct pwc_device *pdev = usb_get_intfdata(intf); | 1219 | struct v4l2_device *v = usb_get_intfdata(intf); |
1220 | struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); | ||
1305 | 1221 | ||
1306 | mutex_lock(&pdev->udevlock); | 1222 | mutex_lock(&pdev->udevlock); |
1307 | mutex_lock(&pdev->modlock); | ||
1308 | |||
1309 | usb_set_intfdata(intf, NULL); | ||
1310 | /* No need to keep the urbs around after disconnection */ | 1223 | /* No need to keep the urbs around after disconnection */ |
1311 | pwc_isoc_cleanup(pdev); | 1224 | pwc_isoc_cleanup(pdev); |
1312 | pwc_cleanup_queued_bufs(pdev); | ||
1313 | pdev->udev = NULL; | 1225 | pdev->udev = NULL; |
1314 | |||
1315 | mutex_unlock(&pdev->modlock); | ||
1316 | mutex_unlock(&pdev->udevlock); | 1226 | mutex_unlock(&pdev->udevlock); |
1317 | 1227 | ||
1318 | pwc_remove_sysfs_files(pdev); | 1228 | pwc_cleanup_queued_bufs(pdev); |
1229 | |||
1319 | video_unregister_device(&pdev->vdev); | 1230 | video_unregister_device(&pdev->vdev); |
1231 | v4l2_device_unregister(&pdev->v4l2_dev); | ||
1320 | 1232 | ||
1321 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 1233 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
1322 | if (pdev->button_dev) | 1234 | if (pdev->button_dev) |
1323 | input_unregister_device(pdev->button_dev); | 1235 | input_unregister_device(pdev->button_dev); |
1324 | #endif | 1236 | #endif |
1237 | |||
1238 | v4l2_device_put(&pdev->v4l2_dev); | ||
1325 | } | 1239 | } |
1326 | 1240 | ||
1327 | 1241 | ||
@@ -1330,7 +1244,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1330 | */ | 1244 | */ |
1331 | 1245 | ||
1332 | static int fps; | 1246 | static int fps; |
1333 | static int compression = -1; | ||
1334 | static int leds[2] = { -1, -1 }; | 1247 | static int leds[2] = { -1, -1 }; |
1335 | static unsigned int leds_nargs; | 1248 | static unsigned int leds_nargs; |
1336 | static char *dev_hint[MAX_DEV_HINTS]; | 1249 | static char *dev_hint[MAX_DEV_HINTS]; |
@@ -1341,7 +1254,6 @@ module_param(fps, int, 0444); | |||
1341 | module_param_named(trace, pwc_trace, int, 0644); | 1254 | module_param_named(trace, pwc_trace, int, 0644); |
1342 | #endif | 1255 | #endif |
1343 | module_param(power_save, int, 0644); | 1256 | module_param(power_save, int, 0644); |
1344 | module_param(compression, int, 0444); | ||
1345 | module_param_array(leds, int, &leds_nargs, 0444); | 1257 | module_param_array(leds, int, &leds_nargs, 0444); |
1346 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); | 1258 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); |
1347 | 1259 | ||
@@ -1350,7 +1262,6 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang | |||
1350 | MODULE_PARM_DESC(trace, "For debugging purposes"); | 1262 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
1351 | #endif | 1263 | #endif |
1352 | MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); | 1264 | MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); |
1353 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); | ||
1354 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); | 1265 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); |
1355 | MODULE_PARM_DESC(dev_hint, "Device node hints"); | 1266 | MODULE_PARM_DESC(dev_hint, "Device node hints"); |
1356 | 1267 | ||
@@ -1384,14 +1295,6 @@ static int __init usb_pwc_init(void) | |||
1384 | PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); | 1295 | PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); |
1385 | } | 1296 | } |
1386 | 1297 | ||
1387 | if (compression >= 0) { | ||
1388 | if (compression > 3) { | ||
1389 | PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); | ||
1390 | return -EINVAL; | ||
1391 | } | ||
1392 | pwc_preferred_compression = compression; | ||
1393 | PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression); | ||
1394 | } | ||
1395 | if (leds[0] >= 0) | 1298 | if (leds[0] >= 0) |
1396 | led_on = leds[0]; | 1299 | led_on = leds[0]; |
1397 | if (leds[1] >= 0) | 1300 | if (leds[1] >= 0) |