diff options
author | Luca Risolia <luca.risolia@studio.unibo.it> | 2007-06-13 14:11:15 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-07-18 13:24:09 -0400 |
commit | 4052fcc7ba32ebd54cc907991cb855d909ce9d1c (patch) | |
tree | 2f1049c2f26d1067fa4e15d74392013c2c091505 | |
parent | 3b2ae0be9e246974db65a5bf4ccd2de328f3dede (diff) |
V4L/DVB (5767): ZC0301 driver updates
- Make the driver depend on V4L2 only (KConfig)
- Better and safe locking mechanism of the device structure on open(), close()
and disconnect()
- Use kref for handling device deallocation
- Generic cleanups
Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/zc0301/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/zc0301/zc0301.h | 21 | ||||
-rw-r--r-- | drivers/media/video/zc0301/zc0301_core.c | 147 | ||||
-rw-r--r-- | drivers/media/video/zc0301/zc0301_pas202bcb.c | 1 | ||||
-rw-r--r-- | drivers/media/video/zc0301/zc0301_pb0330.c | 1 | ||||
-rw-r--r-- | drivers/media/video/zc0301/zc0301_sensor.h | 2 |
6 files changed, 91 insertions, 83 deletions
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index 47cd93f9c7de..edb00293cd59 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config USB_ZC0301 | 1 | config USB_ZC0301 |
2 | tristate "USB ZC0301[P] Image Processor and Control Chip support" | 2 | tristate "USB ZC0301[P] Image Processor and Control Chip support" |
3 | depends on VIDEO_V4L1 | 3 | depends on VIDEO_V4L2 |
4 | ---help--- | 4 | ---help--- |
5 | Say Y here if you want support for cameras based on the ZC0301 or | 5 | Say Y here if you want support for cameras based on the ZC0301 or |
6 | ZC0301P Image Processors and Control Chips. | 6 | ZC0301P Image Processors and Control Chips. |
diff --git a/drivers/media/video/zc0301/zc0301.h b/drivers/media/video/zc0301/zc0301.h index 710f12eb9126..a2de50efa31a 100644 --- a/drivers/media/video/zc0301/zc0301.h +++ b/drivers/media/video/zc0301/zc0301.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/rwsem.h> | 36 | #include <linux/rwsem.h> |
37 | #include <linux/stddef.h> | 37 | #include <linux/stddef.h> |
38 | #include <linux/string.h> | 38 | #include <linux/string.h> |
39 | #include <linux/kref.h> | ||
39 | 40 | ||
40 | #include "zc0301_sensor.h" | 41 | #include "zc0301_sensor.h" |
41 | 42 | ||
@@ -98,7 +99,7 @@ struct zc0301_module_param { | |||
98 | u16 frame_timeout; | 99 | u16 frame_timeout; |
99 | }; | 100 | }; |
100 | 101 | ||
101 | static DECLARE_RWSEM(zc0301_disconnect); | 102 | static DECLARE_RWSEM(zc0301_dev_lock); |
102 | 103 | ||
103 | struct zc0301_device { | 104 | struct zc0301_device { |
104 | struct video_device* v4ldev; | 105 | struct video_device* v4ldev; |
@@ -121,12 +122,14 @@ struct zc0301_device { | |||
121 | 122 | ||
122 | struct zc0301_module_param module_param; | 123 | struct zc0301_module_param module_param; |
123 | 124 | ||
125 | struct kref kref; | ||
124 | enum zc0301_dev_state state; | 126 | enum zc0301_dev_state state; |
125 | u8 users; | 127 | u8 users; |
126 | 128 | ||
127 | struct mutex dev_mutex, fileop_mutex; | 129 | struct completion probe; |
130 | struct mutex open_mutex, fileop_mutex; | ||
128 | spinlock_t queue_lock; | 131 | spinlock_t queue_lock; |
129 | wait_queue_head_t open, wait_frame, wait_stream; | 132 | wait_queue_head_t wait_open, wait_frame, wait_stream; |
130 | }; | 133 | }; |
131 | 134 | ||
132 | /*****************************************************************************/ | 135 | /*****************************************************************************/ |
@@ -156,8 +159,8 @@ do { \ | |||
156 | else if ((level) == 2) \ | 159 | else if ((level) == 2) \ |
157 | dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ | 160 | dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ |
158 | else if ((level) >= 3) \ | 161 | else if ((level) >= 3) \ |
159 | dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ | 162 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", \ |
160 | __FUNCTION__, __LINE__ , ## args); \ | 163 | __FILE__, __FUNCTION__, __LINE__ , ## args); \ |
161 | } \ | 164 | } \ |
162 | } while (0) | 165 | } while (0) |
163 | # define KDBG(level, fmt, args...) \ | 166 | # define KDBG(level, fmt, args...) \ |
@@ -166,8 +169,8 @@ do { \ | |||
166 | if ((level) == 1 || (level) == 2) \ | 169 | if ((level) == 1 || (level) == 2) \ |
167 | pr_info("zc0301: " fmt "\n", ## args); \ | 170 | pr_info("zc0301: " fmt "\n", ## args); \ |
168 | else if ((level) == 3) \ | 171 | else if ((level) == 3) \ |
169 | pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ | 172 | pr_debug("sn9c102: [%s:%s:%d] " fmt "\n", __FILE__, \ |
170 | __LINE__ , ## args); \ | 173 | __FUNCTION__, __LINE__ , ## args); \ |
171 | } \ | 174 | } \ |
172 | } while (0) | 175 | } while (0) |
173 | # define V4LDBG(level, name, cmd) \ | 176 | # define V4LDBG(level, name, cmd) \ |
@@ -183,8 +186,8 @@ do { \ | |||
183 | 186 | ||
184 | #undef PDBG | 187 | #undef PDBG |
185 | #define PDBG(fmt, args...) \ | 188 | #define PDBG(fmt, args...) \ |
186 | dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ | 189 | dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \ |
187 | __FUNCTION__, __LINE__ , ## args) | 190 | __LINE__ , ## args) |
188 | 191 | ||
189 | #undef PDBGG | 192 | #undef PDBGG |
190 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ | 193 | #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index f1120551c70c..703b741e46df 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -49,11 +49,11 @@ | |||
49 | 49 | ||
50 | #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ | 50 | #define ZC0301_MODULE_NAME "V4L2 driver for ZC0301[P] " \ |
51 | "Image Processor and Control Chip" | 51 | "Image Processor and Control Chip" |
52 | #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 52 | #define ZC0301_MODULE_AUTHOR "(C) 2006-2007 Luca Risolia" |
53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 53 | #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
54 | #define ZC0301_MODULE_LICENSE "GPL" | 54 | #define ZC0301_MODULE_LICENSE "GPL" |
55 | #define ZC0301_MODULE_VERSION "1:1.07" | 55 | #define ZC0301_MODULE_VERSION "1:1.10" |
56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 7) | 56 | #define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 10) |
57 | 57 | ||
58 | /*****************************************************************************/ | 58 | /*****************************************************************************/ |
59 | 59 | ||
@@ -573,7 +573,8 @@ static int zc0301_init(struct zc0301_device* cam) | |||
573 | int err = 0; | 573 | int err = 0; |
574 | 574 | ||
575 | if (!(cam->state & DEV_INITIALIZED)) { | 575 | if (!(cam->state & DEV_INITIALIZED)) { |
576 | init_waitqueue_head(&cam->open); | 576 | mutex_init(&cam->open_mutex); |
577 | init_waitqueue_head(&cam->wait_open); | ||
577 | qctrl = s->qctrl; | 578 | qctrl = s->qctrl; |
578 | rect = &(s->cropcap.defrect); | 579 | rect = &(s->cropcap.defrect); |
579 | cam->compression.quality = ZC0301_COMPRESSION_QUALITY; | 580 | cam->compression.quality = ZC0301_COMPRESSION_QUALITY; |
@@ -634,59 +635,73 @@ static int zc0301_init(struct zc0301_device* cam) | |||
634 | return 0; | 635 | return 0; |
635 | } | 636 | } |
636 | 637 | ||
638 | /*****************************************************************************/ | ||
637 | 639 | ||
638 | static void zc0301_release_resources(struct zc0301_device* cam) | 640 | static void zc0301_release_resources(struct kref *kref) |
639 | { | 641 | { |
642 | struct zc0301_device *cam = container_of(kref, struct zc0301_device, | ||
643 | kref); | ||
640 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); | 644 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); |
641 | video_set_drvdata(cam->v4ldev, NULL); | 645 | video_set_drvdata(cam->v4ldev, NULL); |
642 | video_unregister_device(cam->v4ldev); | 646 | video_unregister_device(cam->v4ldev); |
647 | usb_put_dev(cam->usbdev); | ||
643 | kfree(cam->control_buffer); | 648 | kfree(cam->control_buffer); |
649 | kfree(cam); | ||
644 | } | 650 | } |
645 | 651 | ||
646 | /*****************************************************************************/ | ||
647 | 652 | ||
648 | static int zc0301_open(struct inode* inode, struct file* filp) | 653 | static int zc0301_open(struct inode* inode, struct file* filp) |
649 | { | 654 | { |
650 | struct zc0301_device* cam; | 655 | struct zc0301_device* cam; |
651 | int err = 0; | 656 | int err = 0; |
652 | 657 | ||
653 | /* | 658 | if (!down_read_trylock(&zc0301_dev_lock)) |
654 | This is the only safe way to prevent race conditions with | ||
655 | disconnect | ||
656 | */ | ||
657 | if (!down_read_trylock(&zc0301_disconnect)) | ||
658 | return -ERESTARTSYS; | 659 | return -ERESTARTSYS; |
659 | 660 | ||
660 | cam = video_get_drvdata(video_devdata(filp)); | 661 | cam = video_get_drvdata(video_devdata(filp)); |
661 | 662 | ||
662 | if (mutex_lock_interruptible(&cam->dev_mutex)) { | 663 | if (wait_for_completion_interruptible(&cam->probe)) { |
663 | up_read(&zc0301_disconnect); | 664 | up_read(&zc0301_dev_lock); |
664 | return -ERESTARTSYS; | 665 | return -ERESTARTSYS; |
665 | } | 666 | } |
666 | 667 | ||
668 | kref_get(&cam->kref); | ||
669 | |||
670 | if (mutex_lock_interruptible(&cam->open_mutex)) { | ||
671 | kref_put(&cam->kref, zc0301_release_resources); | ||
672 | up_read(&zc0301_dev_lock); | ||
673 | return -ERESTARTSYS; | ||
674 | } | ||
675 | |||
676 | if (cam->state & DEV_DISCONNECTED) { | ||
677 | DBG(1, "Device not present"); | ||
678 | err = -ENODEV; | ||
679 | goto out; | ||
680 | } | ||
681 | |||
667 | if (cam->users) { | 682 | if (cam->users) { |
668 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); | 683 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); |
684 | DBG(3, "Simultaneous opens are not supported"); | ||
669 | if ((filp->f_flags & O_NONBLOCK) || | 685 | if ((filp->f_flags & O_NONBLOCK) || |
670 | (filp->f_flags & O_NDELAY)) { | 686 | (filp->f_flags & O_NDELAY)) { |
671 | err = -EWOULDBLOCK; | 687 | err = -EWOULDBLOCK; |
672 | goto out; | 688 | goto out; |
673 | } | 689 | } |
674 | mutex_unlock(&cam->dev_mutex); | 690 | DBG(2, "A blocking open() has been requested. Wait for the " |
675 | err = wait_event_interruptible_exclusive(cam->open, | 691 | "device to be released..."); |
676 | cam->state & DEV_DISCONNECTED | 692 | up_read(&zc0301_dev_lock); |
693 | err = wait_event_interruptible_exclusive(cam->wait_open, | ||
694 | (cam->state & DEV_DISCONNECTED) | ||
677 | || !cam->users); | 695 | || !cam->users); |
678 | if (err) { | 696 | down_read(&zc0301_dev_lock); |
679 | up_read(&zc0301_disconnect); | 697 | if (err) |
680 | return err; | 698 | goto out; |
681 | } | ||
682 | if (cam->state & DEV_DISCONNECTED) { | 699 | if (cam->state & DEV_DISCONNECTED) { |
683 | up_read(&zc0301_disconnect); | 700 | err = -ENODEV; |
684 | return -ENODEV; | 701 | goto out; |
685 | } | 702 | } |
686 | mutex_lock(&cam->dev_mutex); | ||
687 | } | 703 | } |
688 | 704 | ||
689 | |||
690 | if (cam->state & DEV_MISCONFIGURED) { | 705 | if (cam->state & DEV_MISCONFIGURED) { |
691 | err = zc0301_init(cam); | 706 | err = zc0301_init(cam); |
692 | if (err) { | 707 | if (err) { |
@@ -711,36 +726,32 @@ static int zc0301_open(struct inode* inode, struct file* filp) | |||
711 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); | 726 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); |
712 | 727 | ||
713 | out: | 728 | out: |
714 | mutex_unlock(&cam->dev_mutex); | 729 | mutex_unlock(&cam->open_mutex); |
715 | up_read(&zc0301_disconnect); | 730 | if (err) |
731 | kref_put(&cam->kref, zc0301_release_resources); | ||
732 | up_read(&zc0301_dev_lock); | ||
716 | return err; | 733 | return err; |
717 | } | 734 | } |
718 | 735 | ||
719 | 736 | ||
720 | static int zc0301_release(struct inode* inode, struct file* filp) | 737 | static int zc0301_release(struct inode* inode, struct file* filp) |
721 | { | 738 | { |
722 | struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); | 739 | struct zc0301_device* cam; |
723 | 740 | ||
724 | mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ | 741 | down_write(&zc0301_dev_lock); |
725 | 742 | ||
726 | zc0301_stop_transfer(cam); | 743 | cam = video_get_drvdata(video_devdata(filp)); |
727 | 744 | ||
745 | zc0301_stop_transfer(cam); | ||
728 | zc0301_release_buffers(cam); | 746 | zc0301_release_buffers(cam); |
729 | |||
730 | if (cam->state & DEV_DISCONNECTED) { | ||
731 | zc0301_release_resources(cam); | ||
732 | usb_put_dev(cam->usbdev); | ||
733 | mutex_unlock(&cam->dev_mutex); | ||
734 | kfree(cam); | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | cam->users--; | 747 | cam->users--; |
739 | wake_up_interruptible_nr(&cam->open, 1); | 748 | wake_up_interruptible_nr(&cam->wait_open, 1); |
740 | 749 | ||
741 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); | 750 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); |
742 | 751 | ||
743 | mutex_unlock(&cam->dev_mutex); | 752 | kref_put(&cam->kref, zc0301_release_resources); |
753 | |||
754 | up_write(&zc0301_dev_lock); | ||
744 | 755 | ||
745 | return 0; | 756 | return 0; |
746 | } | 757 | } |
@@ -775,7 +786,7 @@ zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) | |||
775 | DBG(3, "Close and open the device again to choose the read " | 786 | DBG(3, "Close and open the device again to choose the read " |
776 | "method"); | 787 | "method"); |
777 | mutex_unlock(&cam->fileop_mutex); | 788 | mutex_unlock(&cam->fileop_mutex); |
778 | return -EINVAL; | 789 | return -EBUSY; |
779 | } | 790 | } |
780 | 791 | ||
781 | if (cam->io == IO_NONE) { | 792 | if (cam->io == IO_NONE) { |
@@ -953,7 +964,12 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) | |||
953 | return -EIO; | 964 | return -EIO; |
954 | } | 965 | } |
955 | 966 | ||
956 | if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || | 967 | if (!(vma->vm_flags & (VM_WRITE | VM_READ))) { |
968 | mutex_unlock(&cam->fileop_mutex); | ||
969 | return -EACCES; | ||
970 | } | ||
971 | |||
972 | if (cam->io != IO_MMAP || | ||
957 | size != PAGE_ALIGN(cam->frame[0].buf.length)) { | 973 | size != PAGE_ALIGN(cam->frame[0].buf.length)) { |
958 | mutex_unlock(&cam->fileop_mutex); | 974 | mutex_unlock(&cam->fileop_mutex); |
959 | return -EINVAL; | 975 | return -EINVAL; |
@@ -984,7 +1000,6 @@ static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) | |||
984 | 1000 | ||
985 | vma->vm_ops = &zc0301_vm_ops; | 1001 | vma->vm_ops = &zc0301_vm_ops; |
986 | vma->vm_private_data = &cam->frame[i]; | 1002 | vma->vm_private_data = &cam->frame[i]; |
987 | |||
988 | zc0301_vm_open(vma); | 1003 | zc0301_vm_open(vma); |
989 | 1004 | ||
990 | mutex_unlock(&cam->fileop_mutex); | 1005 | mutex_unlock(&cam->fileop_mutex); |
@@ -1211,7 +1226,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) | |||
1211 | if (cam->frame[i].vma_use_count) { | 1226 | if (cam->frame[i].vma_use_count) { |
1212 | DBG(3, "VIDIOC_S_CROP failed. " | 1227 | DBG(3, "VIDIOC_S_CROP failed. " |
1213 | "Unmap the buffers first."); | 1228 | "Unmap the buffers first."); |
1214 | return -EINVAL; | 1229 | return -EBUSY; |
1215 | } | 1230 | } |
1216 | 1231 | ||
1217 | if (!s->set_crop) { | 1232 | if (!s->set_crop) { |
@@ -1434,7 +1449,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, | |||
1434 | if (cam->frame[i].vma_use_count) { | 1449 | if (cam->frame[i].vma_use_count) { |
1435 | DBG(3, "VIDIOC_S_FMT failed. " | 1450 | DBG(3, "VIDIOC_S_FMT failed. " |
1436 | "Unmap the buffers first."); | 1451 | "Unmap the buffers first."); |
1437 | return -EINVAL; | 1452 | return -EBUSY; |
1438 | } | 1453 | } |
1439 | 1454 | ||
1440 | if (cam->stream == STREAM_ON) | 1455 | if (cam->stream == STREAM_ON) |
@@ -1544,14 +1559,14 @@ zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) | |||
1544 | if (cam->io == IO_READ) { | 1559 | if (cam->io == IO_READ) { |
1545 | DBG(3, "Close and open the device again to choose the mmap " | 1560 | DBG(3, "Close and open the device again to choose the mmap " |
1546 | "I/O method"); | 1561 | "I/O method"); |
1547 | return -EINVAL; | 1562 | return -EBUSY; |
1548 | } | 1563 | } |
1549 | 1564 | ||
1550 | for (i = 0; i < cam->nbuffers; i++) | 1565 | for (i = 0; i < cam->nbuffers; i++) |
1551 | if (cam->frame[i].vma_use_count) { | 1566 | if (cam->frame[i].vma_use_count) { |
1552 | DBG(3, "VIDIOC_REQBUFS failed. " | 1567 | DBG(3, "VIDIOC_REQBUFS failed. " |
1553 | "Previous buffers are still mapped."); | 1568 | "Previous buffers are still mapped."); |
1554 | return -EINVAL; | 1569 | return -EBUSY; |
1555 | } | 1570 | } |
1556 | 1571 | ||
1557 | if (cam->stream == STREAM_ON) | 1572 | if (cam->stream == STREAM_ON) |
@@ -1699,9 +1714,6 @@ zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) | |||
1699 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) | 1714 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) |
1700 | return -EINVAL; | 1715 | return -EINVAL; |
1701 | 1716 | ||
1702 | if (list_empty(&cam->inqueue)) | ||
1703 | return -EINVAL; | ||
1704 | |||
1705 | cam->stream = STREAM_ON; | 1717 | cam->stream = STREAM_ON; |
1706 | 1718 | ||
1707 | DBG(3, "Stream on"); | 1719 | DBG(3, "Stream on"); |
@@ -1949,8 +1961,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1949 | goto fail; | 1961 | goto fail; |
1950 | } | 1962 | } |
1951 | 1963 | ||
1952 | mutex_init(&cam->dev_mutex); | ||
1953 | |||
1954 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " | 1964 | DBG(2, "ZC0301[P] Image Processor and Control Chip detected " |
1955 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); | 1965 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); |
1956 | 1966 | ||
@@ -1982,7 +1992,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1982 | cam->v4ldev->release = video_device_release; | 1992 | cam->v4ldev->release = video_device_release; |
1983 | video_set_drvdata(cam->v4ldev, cam); | 1993 | video_set_drvdata(cam->v4ldev, cam); |
1984 | 1994 | ||
1985 | mutex_lock(&cam->dev_mutex); | 1995 | init_completion(&cam->probe); |
1986 | 1996 | ||
1987 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, | 1997 | err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, |
1988 | video_nr[dev_nr]); | 1998 | video_nr[dev_nr]); |
@@ -1992,7 +2002,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1992 | DBG(1, "Free /dev/videoX node not found"); | 2002 | DBG(1, "Free /dev/videoX node not found"); |
1993 | video_nr[dev_nr] = -1; | 2003 | video_nr[dev_nr] = -1; |
1994 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; | 2004 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; |
1995 | mutex_unlock(&cam->dev_mutex); | 2005 | complete_all(&cam->probe); |
1996 | goto fail; | 2006 | goto fail; |
1997 | } | 2007 | } |
1998 | 2008 | ||
@@ -2004,8 +2014,10 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2004 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; | 2014 | dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; |
2005 | 2015 | ||
2006 | usb_set_intfdata(intf, cam); | 2016 | usb_set_intfdata(intf, cam); |
2017 | kref_init(&cam->kref); | ||
2018 | usb_get_dev(cam->usbdev); | ||
2007 | 2019 | ||
2008 | mutex_unlock(&cam->dev_mutex); | 2020 | complete_all(&cam->probe); |
2009 | 2021 | ||
2010 | return 0; | 2022 | return 0; |
2011 | 2023 | ||
@@ -2022,40 +2034,31 @@ fail: | |||
2022 | 2034 | ||
2023 | static void zc0301_usb_disconnect(struct usb_interface* intf) | 2035 | static void zc0301_usb_disconnect(struct usb_interface* intf) |
2024 | { | 2036 | { |
2025 | struct zc0301_device* cam = usb_get_intfdata(intf); | 2037 | struct zc0301_device* cam; |
2026 | |||
2027 | if (!cam) | ||
2028 | return; | ||
2029 | 2038 | ||
2030 | down_write(&zc0301_disconnect); | 2039 | down_write(&zc0301_dev_lock); |
2031 | 2040 | ||
2032 | mutex_lock(&cam->dev_mutex); | 2041 | cam = usb_get_intfdata(intf); |
2033 | 2042 | ||
2034 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | 2043 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); |
2035 | 2044 | ||
2036 | wake_up_interruptible_all(&cam->open); | ||
2037 | |||
2038 | if (cam->users) { | 2045 | if (cam->users) { |
2039 | DBG(2, "Device /dev/video%d is open! Deregistration and " | 2046 | DBG(2, "Device /dev/video%d is open! Deregistration and " |
2040 | "memory deallocation are deferred on close.", | 2047 | "memory deallocation are deferred.", |
2041 | cam->v4ldev->minor); | 2048 | cam->v4ldev->minor); |
2042 | cam->state |= DEV_MISCONFIGURED; | 2049 | cam->state |= DEV_MISCONFIGURED; |
2043 | zc0301_stop_transfer(cam); | 2050 | zc0301_stop_transfer(cam); |
2044 | cam->state |= DEV_DISCONNECTED; | 2051 | cam->state |= DEV_DISCONNECTED; |
2045 | wake_up_interruptible(&cam->wait_frame); | 2052 | wake_up_interruptible(&cam->wait_frame); |
2046 | wake_up(&cam->wait_stream); | 2053 | wake_up(&cam->wait_stream); |
2047 | usb_get_dev(cam->usbdev); | 2054 | } else |
2048 | } else { | ||
2049 | cam->state |= DEV_DISCONNECTED; | 2055 | cam->state |= DEV_DISCONNECTED; |
2050 | zc0301_release_resources(cam); | ||
2051 | } | ||
2052 | 2056 | ||
2053 | mutex_unlock(&cam->dev_mutex); | 2057 | wake_up_interruptible_all(&cam->wait_open); |
2054 | 2058 | ||
2055 | if (!cam->users) | 2059 | kref_put(&cam->kref, zc0301_release_resources); |
2056 | kfree(cam); | ||
2057 | 2060 | ||
2058 | up_write(&zc0301_disconnect); | 2061 | up_write(&zc0301_dev_lock); |
2059 | } | 2062 | } |
2060 | 2063 | ||
2061 | 2064 | ||
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c index 3efb92a0d0da..24b0dfba357e 100644 --- a/drivers/media/video/zc0301/zc0301_pas202bcb.c +++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c | |||
@@ -327,6 +327,7 @@ static struct zc0301_sensor pas202bcb = { | |||
327 | .height = 480, | 327 | .height = 480, |
328 | .pixelformat = V4L2_PIX_FMT_JPEG, | 328 | .pixelformat = V4L2_PIX_FMT_JPEG, |
329 | .priv = 8, | 329 | .priv = 8, |
330 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
330 | }, | 331 | }, |
331 | }; | 332 | }; |
332 | 333 | ||
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c index 5784b1d1491c..9519aba3612e 100644 --- a/drivers/media/video/zc0301/zc0301_pb0330.c +++ b/drivers/media/video/zc0301/zc0301_pb0330.c | |||
@@ -157,6 +157,7 @@ static struct zc0301_sensor pb0330 = { | |||
157 | .height = 480, | 157 | .height = 480, |
158 | .pixelformat = V4L2_PIX_FMT_JPEG, | 158 | .pixelformat = V4L2_PIX_FMT_JPEG, |
159 | .priv = 8, | 159 | .priv = 8, |
160 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
160 | }, | 161 | }, |
161 | }; | 162 | }; |
162 | 163 | ||
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 44e82cff9319..70fe6fc6cdd5 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #define _ZC0301_SENSOR_H_ | 23 | #define _ZC0301_SENSOR_H_ |
24 | 24 | ||
25 | #include <linux/usb.h> | 25 | #include <linux/usb.h> |
26 | #include <linux/videodev.h> | 26 | #include <linux/videodev2.h> |
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/stddef.h> | 28 | #include <linux/stddef.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |