V4L/DVB: gspca - vc032x: Stop the USB exchanges on error

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index de9e4f9..c9df1ac 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -3073,13 +3073,21 @@
 		  u16 index,
 		  u16 len)
 {
-	usb_control_msg(gspca_dev->dev,
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
 			req,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			1,			/* value */
 			index, gspca_dev->usb_buf, len,
 			500);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "reg_r err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 }
 
 static void reg_w(struct usb_device *dev,
@@ -3087,18 +3095,37 @@
 			    u16 value,
 			    u16 index)
 {
-	usb_control_msg(dev,
-			usb_sndctrlpipe(dev, 0),
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(gspca_dev->dev,
+			usb_sndctrlpipe(gspca_dev->dev, 0),
 			req,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0,
 			500);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "reg_w err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+static void reg_w(struct gspca_dev *gspca_dev,
+			    u16 req,
+			    u16 value,
+			    u16 index)
+{
+#ifdef GSPCA_DEBUG
+	if (gspca_dev->usb_err < 0)
+		return;
+	PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
+#endif
+	reg_w_i(gspca_dev, req, value, index);
 }
 
 static u16 read_sensor_register(struct gspca_dev *gspca_dev,
 				u16 address)
 {
-	struct usb_device *dev = gspca_dev->dev;
 	u8 ldata, mdata, hdata;
 	int retry = 50;
 
@@ -3108,8 +3135,8 @@
 			gspca_dev->usb_buf[0]);
 		return 0;
 	}
-	reg_w(dev, 0xa0, address, 0xb33a);
-	reg_w(dev, 0xa0, 0x02, 0xb339);
+	reg_w(gspca_dev, 0xa0, address, 0xb33a);
+	reg_w(gspca_dev, 0xa0, 0x02, 0xb339);
 
 	do {
 		reg_r(gspca_dev, 0xa1, 0xb33b, 1);
@@ -3136,15 +3163,15 @@
 static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int i, n;
 	u16 value;
 	const struct sensor_info *ptsensor_info;
 
 /*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
 	if (sd->flags & FL_SAMSUNG) {
-		reg_w(dev, 0xa0, 0x01, 0xb301);
-		reg_w(dev, 0x89, 0xf0ff, 0xffff); /* select the back sensor */
+		reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
+		reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
+						/* select the back sensor */
 	}
 
 	reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
@@ -3158,13 +3185,13 @@
 		n = ARRAY_SIZE(vc0323_probe_data);
 	}
 	for (i = 0; i < n; i++) {
-		reg_w(dev, 0xa0, 0x02, 0xb334);
-		reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300);
-		reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300);
-		reg_w(dev, 0xa0, 0x01, 0xb308);
-		reg_w(dev, 0xa0, 0x0c, 0xb309);
-		reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
-		reg_w(dev, 0xa0, ptsensor_info->op, 0xb301);
+		reg_w(gspca_dev, 0xa0, 0x02, 0xb334);
+		reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300);
+		reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300);
+		reg_w(gspca_dev, 0xa0, 0x01, 0xb308);
+		reg_w(gspca_dev, 0xa0, 0x0c, 0xb309);
+		reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
+		reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301);
 		value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
 		if (value == 0 && ptsensor_info->IdAdd == 0x82)
 			value = read_sensor_register(gspca_dev, 0x83);
@@ -3192,17 +3219,16 @@
 			u8 reg, const u8 *val,
 			u8 size)		/* 1 or 2 */
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int retry;
 
 	reg_r(gspca_dev, 0xa1, 0xb33f, 1);
 /*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
-	reg_w(dev, 0xa0, size, 0xb334);
-	reg_w(dev, 0xa0, reg, 0xb33a);
-	reg_w(dev, 0xa0, val[0], 0xb336);
+	reg_w(gspca_dev, 0xa0, size, 0xb334);
+	reg_w(gspca_dev, 0xa0, reg, 0xb33a);
+	reg_w(gspca_dev, 0xa0, val[0], 0xb336);
 	if (size > 1)
-		reg_w(dev, 0xa0, val[1], 0xb337);
-	reg_w(dev, 0xa0, 0x01, 0xb339);
+		reg_w(gspca_dev, 0xa0, val[1], 0xb337);
+	reg_w(gspca_dev, 0xa0, 0x01, 0xb339);
 	retry = 4;
 	do {
 		reg_r(gspca_dev, 0xa1, 0xb33b, 1);
@@ -3221,13 +3247,12 @@
 	u16 ad = addr;
 
 	for (j = 0; j < tabsize; j++)
-		reg_w(gspca_dev->dev, 0xa0, tab[j], ad++);
+		reg_w(gspca_dev, 0xa0, tab[j], ad++);
 }
 
 static void usb_exchange(struct gspca_dev *gspca_dev,
 			const u8 data[][4])
 {
-	struct usb_device *dev = gspca_dev->dev;
 	int i = 0;
 
 	for (;;) {
@@ -3235,7 +3260,7 @@
 		default:
 			return;
 		case 0xcc:			/* normal write */
-			reg_w(dev, 0xa0, data[i][2],
+			reg_w(gspca_dev, 0xa0, data[i][2],
 					(data[i][0]) << 8 | data[i][1]);
 			break;
 		case 0xaa:			/* i2c op */
@@ -3259,7 +3284,6 @@
 			const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	struct cam *cam;
 	int sensor;
 	static u8 npkt[] = {	/* number of packets per ISOC message */
@@ -3365,10 +3389,10 @@
 
 	if (sd->bridge == BRIDGE_VC0321) {
 		reg_r(gspca_dev, 0x8a, 0, 3);
-		reg_w(dev, 0x87, 0x00, 0x0f0f);
+		reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
 
 		reg_r(gspca_dev, 0x8b, 0, 3);
-		reg_w(dev, 0x88, 0x00, 0x0202);
+		reg_w(gspca_dev, 0x88, 0x00, 0x0202);
 	}
 	return 0;
 }
@@ -3381,12 +3405,12 @@
 	if (sd->sensor == SENSOR_POxxxx) {
 		reg_r(gspca_dev, 0xa1, 0xb300, 1);
 		if (gspca_dev->usb_buf[0] != 0) {
-			reg_w(gspca_dev->dev, 0xa0, 0x26, 0xb300);
-			reg_w(gspca_dev->dev, 0xa0, 0x04, 0xb300);
-			reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb300);
+			reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
+			reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
+			reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
 		}
 	}
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -3516,17 +3540,17 @@
 
 /*fixme: back sensor only*/
 	if (sd->flags & FL_SAMSUNG) {
-		reg_w(gspca_dev->dev, 0x89, 0xf0ff, 0xffff);
-		reg_w(gspca_dev->dev, 0xa9, 0x8348, 0x000e);
-		reg_w(gspca_dev->dev, 0xa9, 0x0000, 0x001a);
+		reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
+		reg_w(gspca_dev, 0xa9, 0x8348, 0x000e);
+		reg_w(gspca_dev, 0xa9, 0x0000, 0x001a);
 	}
 
 	/* Assume start use the good resolution from gspca_dev->mode */
 	if (sd->bridge == BRIDGE_VC0321) {
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfec);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef);
+		reg_w(gspca_dev, 0xa0, 0xff, 0xbfec);
+		reg_w(gspca_dev, 0xa0, 0xff, 0xbfed);
+		reg_w(gspca_dev, 0xa0, 0xff, 0xbfee);
+		reg_w(gspca_dev, 0xa0, 0xff, 0xbfef);
 		sd->image_offset = 46;
 	} else {
 		if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
@@ -3617,7 +3641,7 @@
 			init = poxxxx_initVGA;
 		usb_exchange(gspca_dev, init);
 		reg_r(gspca_dev, 0x8c, 0x0000, 3);
-		reg_w(gspca_dev->dev, 0xa0,
+		reg_w(gspca_dev, 0xa0,
 				gspca_dev->usb_buf[2] & 1 ? 0 : 1,
 				0xb35c);
 		msleep(300);
@@ -3635,10 +3659,10 @@
 		switch (sd->sensor) {
 		case SENSOR_PO1200:
 		case SENSOR_HV7131R:
-			reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415);
+			reg_w(gspca_dev, 0x89, 0x0400, 0x1415);
 			break;
 		case SENSOR_MI1310_SOC:
-			reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000);
+			reg_w(gspca_dev, 0x89, 0x058c, 0x0000);
 			break;
 		}
 		msleep(100);
@@ -3648,9 +3672,9 @@
 	}
 	switch (sd->sensor) {
 	case SENSOR_OV7670:
-		reg_w(gspca_dev->dev, 0x87, 0xffff, 0xffff);
-		reg_w(gspca_dev->dev, 0x88, 0xff00, 0xf0f1);
-		reg_w(gspca_dev->dev, 0xa0, 0x0000, 0xbfff);
+		reg_w(gspca_dev, 0x87, 0xffff, 0xffff);
+		reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1);
+		reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
 		break;
 	case SENSOR_POxxxx:
 		setcolors(gspca_dev);
@@ -3659,51 +3683,49 @@
 
 		/* led on */
 		msleep(80);
-		reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
+		reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
 		usb_exchange(gspca_dev, poxxxx_init_end_2);
 		break;
 	}
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-	struct usb_device *dev = gspca_dev->dev;
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	switch (sd->sensor) {
 	case SENSOR_MI1310_SOC:
-		reg_w(dev, 0x89, 0x058c, 0x00ff);
+		reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
 		break;
 	case SENSOR_POxxxx:
 		return;
 	default:
 		if (!(sd->flags & FL_SAMSUNG))
-			reg_w(dev, 0x89, 0xffff, 0xffff);
+			reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
 		break;
 	}
-	reg_w(dev, 0xa0, 0x01, 0xb301);
-	reg_w(dev, 0xa0, 0x09, 0xb003);
+	reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
+	reg_w(gspca_dev, 0xa0, 0x09, 0xb003);
 }
 
 /* called on streamoff with alt 0 and on disconnect */
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
-	struct usb_device *dev = gspca_dev->dev;
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	if (!gspca_dev->present)
 		return;
 /*fixme: is this useful?*/
 	if (sd->sensor == SENSOR_MI1310_SOC)
-		reg_w(dev, 0x89, 0x058c, 0x00ff);
+		reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
 	else if (!(sd->flags & FL_SAMSUNG))
-		reg_w(dev, 0x89, 0xffff, 0xffff);
+		reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
 
 	if (sd->sensor == SENSOR_POxxxx) {
-		reg_w(dev, 0xa0, 0x26, 0xb300);
-		reg_w(dev, 0xa0, 0x04, 0xb300);
-		reg_w(dev, 0xa0, 0x00, 0xb300);
+		reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
+		reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
+		reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
 	}
 }
 
@@ -3743,7 +3765,7 @@
 	sd->brightness = val;
 	if (gspca_dev->streaming)
 		setbrightness(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3761,7 +3783,7 @@
 	sd->contrast = val;
 	if (gspca_dev->streaming)
 		setcontrast(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3779,7 +3801,7 @@
 	sd->colors = val;
 	if (gspca_dev->streaming)
 		setcolors(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3797,7 +3819,7 @@
 	sd->hflip = val;
 	if (gspca_dev->streaming)
 		sethvflip(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3815,7 +3837,7 @@
 	sd->vflip = val;
 	if (gspca_dev->streaming)
 		sethvflip(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3833,7 +3855,7 @@
 	sd->lightfreq = val;
 	if (gspca_dev->streaming)
 		setlightfreq(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
@@ -3851,7 +3873,7 @@
 	sd->sharpness = val;
 	if (gspca_dev->streaming)
 		setsharpness(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)