diff options
author | Jean-François Moine <moinejf@free.fr> | 2010-07-06 08:00:07 (GMT) |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-02 19:42:50 (GMT) |
commit | fe854ec07cada95296e882aa795db83409c61eeb (patch) | |
tree | cd55cd23072c534116bf61d12ba8414929a025bb /drivers/media | |
parent | 98475cb642b520a5d50bd6d6abaadfee8688c110 (diff) | |
download | linux-fe854ec07cada95296e882aa795db83409c61eeb.tar.xz |
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>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/vc032x.c | 152 |
1 files changed, 87 insertions, 65 deletions
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 @@ static void reg_r(struct gspca_dev *gspca_dev, 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 @@ static void reg_w(struct usb_device *dev, 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 @@ static u16 read_sensor_register(struct gspca_dev *gspca_dev, 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 u16 read_sensor_register(struct gspca_dev *gspca_dev, 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 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) 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 @@ static void i2c_write(struct gspca_dev *gspca_dev, 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 @@ static void put_tab_to_reg(struct gspca_dev *gspca_dev, 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 @@ static void usb_exchange(struct gspca_dev *gspca_dev, 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 @@ static int sd_config(struct gspca_dev *gspca_dev, 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 @@ static int sd_config(struct gspca_dev *gspca_dev, 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 @@ static int sd_init(struct gspca_dev *gspca_dev) 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 @@ static int sd_start(struct gspca_dev *gspca_dev) /*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 @@ static int sd_start(struct gspca_dev *gspca_dev) 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 @@ static int sd_start(struct gspca_dev *gspca_dev) 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 @@ static int sd_start(struct gspca_dev *gspca_dev) } 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 @@ static int sd_start(struct gspca_dev *gspca_dev) /* 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 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) 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 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) 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) |