|
@@ -613,6 +613,37 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int gspca_set_alt0(struct gspca_dev *gspca_dev)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (gspca_dev->alt == 0)
|
|
|
+ return 0;
|
|
|
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
|
|
|
+ if (ret < 0)
|
|
|
+ PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/* Note: both the queue and the usb locks should be held when calling this */
|
|
|
+static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
|
|
+{
|
|
|
+ gspca_dev->streaming = 0;
|
|
|
+ if (gspca_dev->present) {
|
|
|
+ if (gspca_dev->sd_desc->stopN)
|
|
|
+ gspca_dev->sd_desc->stopN(gspca_dev);
|
|
|
+ destroy_urbs(gspca_dev);
|
|
|
+ gspca_input_destroy_urb(gspca_dev);
|
|
|
+ gspca_set_alt0(gspca_dev);
|
|
|
+ gspca_input_create_urb(gspca_dev);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* always call stop0 to free the subdriver's resources */
|
|
|
+ if (gspca_dev->sd_desc->stop0)
|
|
|
+ gspca_dev->sd_desc->stop0(gspca_dev);
|
|
|
+ PDEBUG(D_STREAM, "stream off OK");
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* look for an input transfer endpoint in an alternate setting
|
|
|
*/
|
|
@@ -838,8 +869,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
|
|
|
}
|
|
|
if (ret >= 0)
|
|
|
break;
|
|
|
- gspca_dev->streaming = 0;
|
|
|
- destroy_urbs(gspca_dev);
|
|
|
+ gspca_stream_off(gspca_dev);
|
|
|
if (ret != -ENOSPC) {
|
|
|
PDEBUG(D_ERR|D_STREAM,
|
|
|
"usb_submit_urb alt %d err %d",
|
|
@@ -869,37 +899,6 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int gspca_set_alt0(struct gspca_dev *gspca_dev)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (gspca_dev->alt == 0)
|
|
|
- return 0;
|
|
|
- ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
|
|
|
- if (ret < 0)
|
|
|
- PDEBUG(D_ERR|D_STREAM, "set alt 0 err %d", ret);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-/* Note: both the queue and the usb locks should be held when calling this */
|
|
|
-static void gspca_stream_off(struct gspca_dev *gspca_dev)
|
|
|
-{
|
|
|
- gspca_dev->streaming = 0;
|
|
|
- if (gspca_dev->present) {
|
|
|
- if (gspca_dev->sd_desc->stopN)
|
|
|
- gspca_dev->sd_desc->stopN(gspca_dev);
|
|
|
- destroy_urbs(gspca_dev);
|
|
|
- gspca_input_destroy_urb(gspca_dev);
|
|
|
- gspca_set_alt0(gspca_dev);
|
|
|
- gspca_input_create_urb(gspca_dev);
|
|
|
- }
|
|
|
-
|
|
|
- /* always call stop0 to free the subdriver's resources */
|
|
|
- if (gspca_dev->sd_desc->stop0)
|
|
|
- gspca_dev->sd_desc->stop0(gspca_dev);
|
|
|
- PDEBUG(D_STREAM, "stream off OK");
|
|
|
-}
|
|
|
-
|
|
|
static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
|
|
|
{
|
|
|
int i;
|