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>
This commit is contained in:
Jean-François Moine 2010-07-06 05:00:07 -03:00 committed by Mauro Carvalho Chehab
parent 98475cb642
commit fe854ec07c

View file

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