aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/gspca.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2009-02-12 06:05:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:49 -0400
commit090264e508c20baa0c3eea5a7d8eea4db84a29cc (patch)
tree4c481782c5b78444f3b50f7507ce7ef9f2722706 /drivers/media/video/gspca/gspca.c
parent10711d07c109a1b2b3245d68ada6aba5c8c59147 (diff)
V4L/DVB (10620): gspca - main: More checks of the device disconnection.
- prevent application oops when the device is disconnected - wake up the application at disconnection time - check the disconnection in ioctl dqbuf and poll Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r--drivers/media/video/gspca/gspca.c105
1 files changed, 74 insertions, 31 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index eac7aec44254..8aac7a1e8f33 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -132,11 +132,13 @@ static void fill_frame(struct gspca_dev *gspca_dev,
132 cam_pkt_op pkt_scan; 132 cam_pkt_op pkt_scan;
133 133
134 if (urb->status != 0) { 134 if (urb->status != 0) {
135 if (urb->status == -ESHUTDOWN)
136 return; /* disconnection */
135#ifdef CONFIG_PM 137#ifdef CONFIG_PM
136 if (!gspca_dev->frozen) 138 if (!gspca_dev->frozen)
137#endif 139#endif
138 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); 140 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
139 return; /* disconnection ? */ 141 return;
140 } 142 }
141 pkt_scan = gspca_dev->sd_desc->pkt_scan; 143 pkt_scan = gspca_dev->sd_desc->pkt_scan;
142 for (i = 0; i < urb->number_of_packets; i++) { 144 for (i = 0; i < urb->number_of_packets; i++) {
@@ -208,6 +210,8 @@ static void bulk_irq(struct urb *urb)
208 switch (urb->status) { 210 switch (urb->status) {
209 case 0: 211 case 0:
210 break; 212 break;
213 case -ESHUTDOWN:
214 return; /* disconnection */
211 case -ECONNRESET: 215 case -ECONNRESET:
212 urb->status = 0; 216 urb->status = 0;
213 break; 217 break;
@@ -216,7 +220,7 @@ static void bulk_irq(struct urb *urb)
216 if (!gspca_dev->frozen) 220 if (!gspca_dev->frozen)
217#endif 221#endif
218 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); 222 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
219 return; /* disconnection ? */ 223 return;
220 } 224 }
221 225
222 /* check the availability of the frame buffer */ 226 /* check the availability of the frame buffer */
@@ -422,10 +426,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
422 if (urb == NULL) 426 if (urb == NULL)
423 break; 427 break;
424 428
425 BUG_ON(!gspca_dev->dev);
426 gspca_dev->urb[i] = NULL; 429 gspca_dev->urb[i] = NULL;
427 if (!gspca_dev->present) 430 usb_kill_urb(urb);
428 usb_kill_urb(urb);
429 if (urb->transfer_buffer != NULL) 431 if (urb->transfer_buffer != NULL)
430 usb_buffer_free(gspca_dev->dev, 432 usb_buffer_free(gspca_dev->dev,
431 urb->transfer_buffer_length, 433 urb->transfer_buffer_length,
@@ -593,6 +595,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
593 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 595 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
594 return -ERESTARTSYS; 596 return -ERESTARTSYS;
595 597
598 if (!gspca_dev->present) {
599 ret = -ENODEV;
600 goto out;
601 }
602
596 /* set the higher alternate setting and 603 /* set the higher alternate setting and
597 * loop until urb submit succeeds */ 604 * loop until urb submit succeeds */
598 gspca_dev->alt = gspca_dev->nbalt; 605 gspca_dev->alt = gspca_dev->nbalt;
@@ -662,12 +669,14 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
662static void gspca_stream_off(struct gspca_dev *gspca_dev) 669static void gspca_stream_off(struct gspca_dev *gspca_dev)
663{ 670{
664 gspca_dev->streaming = 0; 671 gspca_dev->streaming = 0;
665 if (gspca_dev->present 672 if (gspca_dev->present) {
666 && gspca_dev->sd_desc->stopN) 673 if (gspca_dev->sd_desc->stopN)
667 gspca_dev->sd_desc->stopN(gspca_dev); 674 gspca_dev->sd_desc->stopN(gspca_dev);
668 destroy_urbs(gspca_dev); 675 destroy_urbs(gspca_dev);
669 if (gspca_dev->present)
670 gspca_set_alt0(gspca_dev); 676 gspca_set_alt0(gspca_dev);
677 }
678
679 /* always call stop0 to free the subdriver's resources */
671 if (gspca_dev->sd_desc->stop0) 680 if (gspca_dev->sd_desc->stop0)
672 gspca_dev->sd_desc->stop0(gspca_dev); 681 gspca_dev->sd_desc->stop0(gspca_dev);
673 PDEBUG(D_STREAM, "stream off OK"); 682 PDEBUG(D_STREAM, "stream off OK");
@@ -949,8 +958,17 @@ static int vidioc_querycap(struct file *file, void *priv,
949 struct v4l2_capability *cap) 958 struct v4l2_capability *cap)
950{ 959{
951 struct gspca_dev *gspca_dev = priv; 960 struct gspca_dev *gspca_dev = priv;
961 int ret;
952 962
953 memset(cap, 0, sizeof *cap); 963 memset(cap, 0, sizeof *cap);
964
965 /* protect the access to the usb device */
966 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
967 return -ERESTARTSYS;
968 if (!gspca_dev->present) {
969 ret = -ENODEV;
970 goto out;
971 }
954 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver); 972 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
955 if (gspca_dev->dev->product != NULL) { 973 if (gspca_dev->dev->product != NULL) {
956 strncpy(cap->card, gspca_dev->dev->product, 974 strncpy(cap->card, gspca_dev->dev->product,
@@ -966,7 +984,10 @@ static int vidioc_querycap(struct file *file, void *priv,
966 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE 984 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
967 | V4L2_CAP_STREAMING 985 | V4L2_CAP_STREAMING
968 | V4L2_CAP_READWRITE; 986 | V4L2_CAP_READWRITE;
969 return 0; 987 ret = 0;
988out:
989 mutex_unlock(&gspca_dev->usb_lock);
990 return ret;
970} 991}
971 992
972static int vidioc_queryctrl(struct file *file, void *priv, 993static int vidioc_queryctrl(struct file *file, void *priv,
@@ -1029,7 +1050,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1029 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); 1050 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
1030 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1051 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1031 return -ERESTARTSYS; 1052 return -ERESTARTSYS;
1032 ret = ctrls->set(gspca_dev, ctrl->value); 1053 if (gspca_dev->present)
1054 ret = ctrls->set(gspca_dev, ctrl->value);
1055 else
1056 ret = -ENODEV;
1033 mutex_unlock(&gspca_dev->usb_lock); 1057 mutex_unlock(&gspca_dev->usb_lock);
1034 return ret; 1058 return ret;
1035 } 1059 }
@@ -1053,7 +1077,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
1053 return -EINVAL; 1077 return -EINVAL;
1054 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1078 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1055 return -ERESTARTSYS; 1079 return -ERESTARTSYS;
1056 ret = ctrls->get(gspca_dev, &ctrl->value); 1080 if (gspca_dev->present)
1081 ret = ctrls->get(gspca_dev, &ctrl->value);
1082 else
1083 ret = -ENODEV;
1057 mutex_unlock(&gspca_dev->usb_lock); 1084 mutex_unlock(&gspca_dev->usb_lock);
1058 return ret; 1085 return ret;
1059 } 1086 }
@@ -1215,10 +1242,7 @@ static int vidioc_streamon(struct file *file, void *priv,
1215 return -EINVAL; 1242 return -EINVAL;
1216 if (mutex_lock_interruptible(&gspca_dev->queue_lock)) 1243 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1217 return -ERESTARTSYS; 1244 return -ERESTARTSYS;
1218 if (!gspca_dev->present) { 1245
1219 ret = -ENODEV;
1220 goto out;
1221 }
1222 if (gspca_dev->nframes == 0 1246 if (gspca_dev->nframes == 0
1223 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) { 1247 || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
1224 ret = -EINVAL; 1248 ret = -EINVAL;
@@ -1286,7 +1310,10 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
1286 return -EINVAL; 1310 return -EINVAL;
1287 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1311 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1288 return -ERESTARTSYS; 1312 return -ERESTARTSYS;
1289 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); 1313 if (gspca_dev->present)
1314 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1315 else
1316 ret = -ENODEV;
1290 mutex_unlock(&gspca_dev->usb_lock); 1317 mutex_unlock(&gspca_dev->usb_lock);
1291 return ret; 1318 return ret;
1292} 1319}
@@ -1301,7 +1328,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
1301 return -EINVAL; 1328 return -EINVAL;
1302 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1329 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1303 return -ERESTARTSYS; 1330 return -ERESTARTSYS;
1304 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); 1331 if (gspca_dev->present)
1332 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1333 else
1334 ret = -ENODEV;
1305 mutex_unlock(&gspca_dev->usb_lock); 1335 mutex_unlock(&gspca_dev->usb_lock);
1306 return ret; 1336 return ret;
1307} 1337}
@@ -1320,7 +1350,11 @@ static int vidioc_g_parm(struct file *filp, void *priv,
1320 1350
1321 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1351 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1322 return -ERESTARTSYS; 1352 return -ERESTARTSYS;
1323 ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm); 1353 if (gspca_dev->present)
1354 ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
1355 parm);
1356 else
1357 ret = -ENODEV;
1324 mutex_unlock(&gspca_dev->usb_lock); 1358 mutex_unlock(&gspca_dev->usb_lock);
1325 return ret; 1359 return ret;
1326 } 1360 }
@@ -1345,7 +1379,11 @@ static int vidioc_s_parm(struct file *filp, void *priv,
1345 1379
1346 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) 1380 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1347 return -ERESTARTSYS; 1381 return -ERESTARTSYS;
1348 ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm); 1382 if (gspca_dev->present)
1383 ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
1384 parm);
1385 else
1386 ret = -ENODEV;
1349 mutex_unlock(&gspca_dev->usb_lock); 1387 mutex_unlock(&gspca_dev->usb_lock);
1350 return ret; 1388 return ret;
1351 } 1389 }
@@ -1519,7 +1557,8 @@ static int frame_wait(struct gspca_dev *gspca_dev,
1519 1557
1520 if (gspca_dev->sd_desc->dq_callback) { 1558 if (gspca_dev->sd_desc->dq_callback) {
1521 mutex_lock(&gspca_dev->usb_lock); 1559 mutex_lock(&gspca_dev->usb_lock);
1522 gspca_dev->sd_desc->dq_callback(gspca_dev); 1560 if (gspca_dev->present)
1561 gspca_dev->sd_desc->dq_callback(gspca_dev);
1523 mutex_unlock(&gspca_dev->usb_lock); 1562 mutex_unlock(&gspca_dev->usb_lock);
1524 } 1563 }
1525 return j; 1564 return j;
@@ -1541,6 +1580,9 @@ static int vidioc_dqbuf(struct file *file, void *priv,
1541 if (v4l2_buf->memory != gspca_dev->memory) 1580 if (v4l2_buf->memory != gspca_dev->memory)
1542 return -EINVAL; 1581 return -EINVAL;
1543 1582
1583 if (!gspca_dev->present)
1584 return -ENODEV;
1585
1544 /* if not streaming, be sure the application will not loop forever */ 1586 /* if not streaming, be sure the application will not loop forever */
1545 if (!(file->f_flags & O_NONBLOCK) 1587 if (!(file->f_flags & O_NONBLOCK)
1546 && !gspca_dev->streaming && gspca_dev->users == 1) 1588 && !gspca_dev->streaming && gspca_dev->users == 1)
@@ -1691,8 +1733,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
1691 PDEBUG(D_FRAM, "poll"); 1733 PDEBUG(D_FRAM, "poll");
1692 1734
1693 poll_wait(file, &gspca_dev->wq, wait); 1735 poll_wait(file, &gspca_dev->wq, wait);
1694 if (!gspca_dev->present)
1695 return POLLERR;
1696 1736
1697 /* if reqbufs is not done, the user would use read() */ 1737 /* if reqbufs is not done, the user would use read() */
1698 if (gspca_dev->nframes == 0) { 1738 if (gspca_dev->nframes == 0) {
@@ -1705,10 +1745,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
1705 1745
1706 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) 1746 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1707 return POLLERR; 1747 return POLLERR;
1708 if (!gspca_dev->present) {
1709 ret = POLLERR;
1710 goto out;
1711 }
1712 1748
1713 /* check the next incoming buffer */ 1749 /* check the next incoming buffer */
1714 i = gspca_dev->fr_o; 1750 i = gspca_dev->fr_o;
@@ -1717,8 +1753,9 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
1717 ret = POLLIN | POLLRDNORM; /* something to read */ 1753 ret = POLLIN | POLLRDNORM; /* something to read */
1718 else 1754 else
1719 ret = 0; 1755 ret = 0;
1720out:
1721 mutex_unlock(&gspca_dev->queue_lock); 1756 mutex_unlock(&gspca_dev->queue_lock);
1757 if (!gspca_dev->present)
1758 return POLLHUP;
1722 return ret; 1759 return ret;
1723} 1760}
1724 1761
@@ -1944,10 +1981,16 @@ void gspca_disconnect(struct usb_interface *intf)
1944 1981
1945 mutex_lock(&gspca_dev->usb_lock); 1982 mutex_lock(&gspca_dev->usb_lock);
1946 gspca_dev->present = 0; 1983 gspca_dev->present = 0;
1947 mutex_unlock(&gspca_dev->usb_lock);
1948 1984
1949 destroy_urbs(gspca_dev); 1985 if (gspca_dev->streaming) {
1986 destroy_urbs(gspca_dev);
1987 wake_up_interruptible(&gspca_dev->wq);
1988 }
1989
1990 /* the device is freed at exit of this function */
1950 gspca_dev->dev = NULL; 1991 gspca_dev->dev = NULL;
1992 mutex_unlock(&gspca_dev->usb_lock);
1993
1951 usb_set_intfdata(intf, NULL); 1994 usb_set_intfdata(intf, NULL);
1952 1995
1953 /* release the device */ 1996 /* release the device */