aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc/pwc-if.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
-rw-r--r--drivers/media/video/pwc/pwc-if.c152
1 files changed, 47 insertions, 105 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 356cd42b593..b0bde5a87c8 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -40,7 +40,7 @@
40 Oh yes, convention: to disctinguish between all the various pointers to 40 Oh yes, convention: to disctinguish between all the various pointers to
41 device-structures, I use these names for the pointer variables: 41 device-structures, I use these names for the pointer variables:
42 udev: struct usb_device * 42 udev: struct usb_device *
43 vdev: struct video_device * 43 vdev: struct video_device (member of pwc_dev)
44 pdev: struct pwc_devive * 44 pdev: struct pwc_devive *
45*/ 45*/
46 46
@@ -152,6 +152,7 @@ static 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 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);
155static void pwc_video_release(struct video_device *vfd);
155 156
156static const struct v4l2_file_operations pwc_fops = { 157static const struct v4l2_file_operations pwc_fops = {
157 .owner = THIS_MODULE, 158 .owner = THIS_MODULE,
@@ -164,42 +165,12 @@ static const struct v4l2_file_operations pwc_fops = {
164}; 165};
165static struct video_device pwc_template = { 166static struct video_device pwc_template = {
166 .name = "Philips Webcam", /* Filled in later */ 167 .name = "Philips Webcam", /* Filled in later */
167 .release = video_device_release, 168 .release = pwc_video_release,
168 .fops = &pwc_fops, 169 .fops = &pwc_fops,
170 .ioctl_ops = &pwc_ioctl_ops,
169}; 171};
170 172
171/***************************************************************************/ 173/***************************************************************************/
172
173/* Okay, this is some magic that I worked out and the reasoning behind it...
174
175 The biggest problem with any USB device is of course: "what to do
176 when the user unplugs the device while it is in use by an application?"
177 We have several options:
178 1) Curse them with the 7 plagues when they do (requires divine intervention)
179 2) Tell them not to (won't work: they'll do it anyway)
180 3) Oops the kernel (this will have a negative effect on a user's uptime)
181 4) Do something sensible.
182
183 Of course, we go for option 4.
184
185 It happens that this device will be linked to two times, once from
186 usb_device and once from the video_device in their respective 'private'
187 pointers. This is done when the device is probed() and all initialization
188 succeeded. The pwc_device struct links back to both structures.
189
190 When a device is unplugged while in use it will be removed from the
191 list of known USB devices; I also de-register it as a V4L device, but
192 unfortunately I can't free the memory since the struct is still in use
193 by the file descriptor. This free-ing is then deferend until the first
194 opportunity. Crude, but it works.
195
196 A small 'advantage' is that if a user unplugs the cam and plugs it back
197 in, it should get assigned the same video device minor, but unfortunately
198 it's non-trivial to re-link the cam back to the video device... (that
199 would surely be magic! :))
200*/
201
202/***************************************************************************/
203/* Private functions */ 174/* Private functions */
204 175
205/* Here we want the physical address of the memory. 176/* Here we want the physical address of the memory.
@@ -1016,16 +987,15 @@ static ssize_t show_snapshot_button_status(struct device *class_dev,
1016static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, 987static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
1017 NULL); 988 NULL);
1018 989
1019static int pwc_create_sysfs_files(struct video_device *vdev) 990static int pwc_create_sysfs_files(struct pwc_device *pdev)
1020{ 991{
1021 struct pwc_device *pdev = video_get_drvdata(vdev);
1022 int rc; 992 int rc;
1023 993
1024 rc = device_create_file(&vdev->dev, &dev_attr_button); 994 rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
1025 if (rc) 995 if (rc)
1026 goto err; 996 goto err;
1027 if (pdev->features & FEATURE_MOTOR_PANTILT) { 997 if (pdev->features & FEATURE_MOTOR_PANTILT) {
1028 rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt); 998 rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
1029 if (rc) 999 if (rc)
1030 goto err_button; 1000 goto err_button;
1031 } 1001 }
@@ -1033,19 +1003,17 @@ static int pwc_create_sysfs_files(struct video_device *vdev)
1033 return 0; 1003 return 0;
1034 1004
1035err_button: 1005err_button:
1036 device_remove_file(&vdev->dev, &dev_attr_button); 1006 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
1037err: 1007err:
1038 PWC_ERROR("Could not create sysfs files.\n"); 1008 PWC_ERROR("Could not create sysfs files.\n");
1039 return rc; 1009 return rc;
1040} 1010}
1041 1011
1042static void pwc_remove_sysfs_files(struct video_device *vdev) 1012static void pwc_remove_sysfs_files(struct pwc_device *pdev)
1043{ 1013{
1044 struct pwc_device *pdev = video_get_drvdata(vdev);
1045
1046 if (pdev->features & FEATURE_MOTOR_PANTILT) 1014 if (pdev->features & FEATURE_MOTOR_PANTILT)
1047 device_remove_file(&vdev->dev, &dev_attr_pan_tilt); 1015 device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
1048 device_remove_file(&vdev->dev, &dev_attr_button); 1016 device_remove_file(&pdev->vdev.dev, &dev_attr_button);
1049} 1017}
1050 1018
1051#ifdef CONFIG_USB_PWC_DEBUG 1019#ifdef CONFIG_USB_PWC_DEBUG
@@ -1106,7 +1074,7 @@ static int pwc_video_open(struct file *file)
1106 if (ret >= 0) 1074 if (ret >= 0)
1107 { 1075 {
1108 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n", 1076 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1109 pdev->vdev->name, 1077 pdev->vdev.name,
1110 pwc_sensor_type_to_string(i), i); 1078 pwc_sensor_type_to_string(i), i);
1111 } 1079 }
1112 } 1080 }
@@ -1180,16 +1148,15 @@ static int pwc_video_open(struct file *file)
1180 return 0; 1148 return 0;
1181} 1149}
1182 1150
1183 1151static void pwc_video_release(struct video_device *vfd)
1184static void pwc_cleanup(struct pwc_device *pdev)
1185{ 1152{
1186 pwc_remove_sysfs_files(pdev->vdev); 1153 struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
1187 video_unregister_device(pdev->vdev); 1154 int hint;
1188 1155
1189#ifdef CONFIG_USB_PWC_INPUT_EVDEV 1156 /* search device_hint[] table if we occupy a slot, by any chance */
1190 if (pdev->button_dev) 1157 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1191 input_unregister_device(pdev->button_dev); 1158 if (device_hint[hint].pdev == pdev)
1192#endif 1159 device_hint[hint].pdev = NULL;
1193 1160
1194 kfree(pdev); 1161 kfree(pdev);
1195} 1162}
@@ -1199,7 +1166,7 @@ static int pwc_video_close(struct file *file)
1199{ 1166{
1200 struct video_device *vdev = file->private_data; 1167 struct video_device *vdev = file->private_data;
1201 struct pwc_device *pdev; 1168 struct pwc_device *pdev;
1202 int i, hint; 1169 int i;
1203 1170
1204 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); 1171 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
1205 1172
@@ -1234,12 +1201,6 @@ static int pwc_video_close(struct file *file)
1234 } 1201 }
1235 pdev->vopen--; 1202 pdev->vopen--;
1236 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); 1203 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
1237 } else {
1238 pwc_cleanup(pdev);
1239 /* search device_hint[] table if we occupy a slot, by any chance */
1240 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1241 if (device_hint[hint].pdev == pdev)
1242 device_hint[hint].pdev = NULL;
1243 } 1204 }
1244 1205
1245 return 0; 1206 return 0;
@@ -1715,19 +1676,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1715 init_waitqueue_head(&pdev->frameq); 1676 init_waitqueue_head(&pdev->frameq);
1716 pdev->vcompression = pwc_preferred_compression; 1677 pdev->vcompression = pwc_preferred_compression;
1717 1678
1718 /* Allocate video_device structure */ 1679 /* Init video_device structure */
1719 pdev->vdev = video_device_alloc(); 1680 memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
1720 if (!pdev->vdev) { 1681 pdev->vdev.parent = &intf->dev;
1721 PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); 1682 pdev->vdev.lock = &pdev->modlock;
1722 rc = -ENOMEM; 1683 strcpy(pdev->vdev.name, name);
1723 goto err_free_mem; 1684 video_set_drvdata(&pdev->vdev, pdev);
1724 }
1725 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
1726 pdev->vdev->parent = &intf->dev;
1727 pdev->vdev->lock = &pdev->modlock;
1728 pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
1729 strcpy(pdev->vdev->name, name);
1730 video_set_drvdata(pdev->vdev, pdev);
1731 1685
1732 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); 1686 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
1733 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); 1687 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
@@ -1746,8 +1700,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1746 } 1700 }
1747 } 1701 }
1748 1702
1749 pdev->vdev->release = video_device_release;
1750
1751 /* occupy slot */ 1703 /* occupy slot */
1752 if (hint < MAX_DEV_HINTS) 1704 if (hint < MAX_DEV_HINTS)
1753 device_hint[hint].pdev = pdev; 1705 device_hint[hint].pdev = pdev;
@@ -1759,16 +1711,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1759 pwc_set_leds(pdev, 0, 0); 1711 pwc_set_leds(pdev, 0, 0);
1760 pwc_camera_power(pdev, 0); 1712 pwc_camera_power(pdev, 0);
1761 1713
1762 rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); 1714 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
1763 if (rc < 0) { 1715 if (rc < 0) {
1764 PWC_ERROR("Failed to register as video device (%d).\n", rc); 1716 PWC_ERROR("Failed to register as video device (%d).\n", rc);
1765 goto err_video_release; 1717 goto err_free_mem;
1766 } 1718 }
1767 rc = pwc_create_sysfs_files(pdev->vdev); 1719 rc = pwc_create_sysfs_files(pdev);
1768 if (rc) 1720 if (rc)
1769 goto err_video_unreg; 1721 goto err_video_unreg;
1770 1722
1771 PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev)); 1723 PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
1772 1724
1773#ifdef CONFIG_USB_PWC_INPUT_EVDEV 1725#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1774 /* register webcam snapshot button input device */ 1726 /* register webcam snapshot button input device */
@@ -1776,7 +1728,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1776 if (!pdev->button_dev) { 1728 if (!pdev->button_dev) {
1777 PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); 1729 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
1778 rc = -ENOMEM; 1730 rc = -ENOMEM;
1779 pwc_remove_sysfs_files(pdev->vdev); 1731 pwc_remove_sysfs_files(pdev);
1780 goto err_video_unreg; 1732 goto err_video_unreg;
1781 } 1733 }
1782 1734
@@ -1794,7 +1746,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1794 if (rc) { 1746 if (rc) {
1795 input_free_device(pdev->button_dev); 1747 input_free_device(pdev->button_dev);
1796 pdev->button_dev = NULL; 1748 pdev->button_dev = NULL;
1797 pwc_remove_sysfs_files(pdev->vdev); 1749 pwc_remove_sysfs_files(pdev);
1798 goto err_video_unreg; 1750 goto err_video_unreg;
1799 } 1751 }
1800#endif 1752#endif
@@ -1804,10 +1756,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1804err_video_unreg: 1756err_video_unreg:
1805 if (hint < MAX_DEV_HINTS) 1757 if (hint < MAX_DEV_HINTS)
1806 device_hint[hint].pdev = NULL; 1758 device_hint[hint].pdev = NULL;
1807 video_unregister_device(pdev->vdev); 1759 video_unregister_device(&pdev->vdev);
1808 pdev->vdev = NULL; /* So we don't try to release it below */
1809err_video_release:
1810 video_device_release(pdev->vdev);
1811err_free_mem: 1760err_free_mem:
1812 kfree(pdev); 1761 kfree(pdev);
1813 return rc; 1762 return rc;
@@ -1816,10 +1765,8 @@ err_free_mem:
1816/* The user yanked out the cable... */ 1765/* The user yanked out the cable... */
1817static void usb_pwc_disconnect(struct usb_interface *intf) 1766static void usb_pwc_disconnect(struct usb_interface *intf)
1818{ 1767{
1819 struct pwc_device *pdev; 1768 struct pwc_device *pdev = usb_get_intfdata(intf);
1820 int hint;
1821 1769
1822 pdev = usb_get_intfdata (intf);
1823 mutex_lock(&pdev->modlock); 1770 mutex_lock(&pdev->modlock);
1824 usb_set_intfdata (intf, NULL); 1771 usb_set_intfdata (intf, NULL);
1825 if (pdev == NULL) { 1772 if (pdev == NULL) {
@@ -1836,30 +1783,25 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
1836 } 1783 }
1837 1784
1838 /* We got unplugged; this is signalled by an EPIPE error code */ 1785 /* We got unplugged; this is signalled by an EPIPE error code */
1839 if (pdev->vopen) { 1786 pdev->error_status = EPIPE;
1840 PWC_INFO("Disconnected while webcam is in use!\n"); 1787 pdev->unplugged = 1;
1841 pdev->error_status = EPIPE;
1842 }
1843 1788
1844 /* Alert waiting processes */ 1789 /* Alert waiting processes */
1845 wake_up_interruptible(&pdev->frameq); 1790 wake_up_interruptible(&pdev->frameq);
1846 /* Wait until device is closed */
1847 if (pdev->vopen) {
1848 pdev->unplugged = 1;
1849 pwc_iso_stop(pdev);
1850 } else {
1851 /* Device is closed, so we can safely unregister it */
1852 PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
1853 1791
1854disconnect_out: 1792 /* No need to keep the urbs around after disconnection */
1855 /* search device_hint[] table if we occupy a slot, by any chance */ 1793 pwc_isoc_cleanup(pdev);
1856 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1857 if (device_hint[hint].pdev == pdev)
1858 device_hint[hint].pdev = NULL;
1859 }
1860 1794
1795disconnect_out:
1861 mutex_unlock(&pdev->modlock); 1796 mutex_unlock(&pdev->modlock);
1862 pwc_cleanup(pdev); 1797
1798 pwc_remove_sysfs_files(pdev);
1799 video_unregister_device(&pdev->vdev);
1800
1801#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1802 if (pdev->button_dev)
1803 input_unregister_device(pdev->button_dev);
1804#endif
1863} 1805}
1864 1806
1865 1807