Commit 14799f6c authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab

V4L/DVB: gspca - pac7311: Use usb_err to propagate USB errors

Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent be927bef
...@@ -258,12 +258,14 @@ static const __u8 page4_7311[] = { ...@@ -258,12 +258,14 @@ static const __u8 page4_7311[] = {
0x23, 0x28, 0x04, 0x11, 0x00, 0x00 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
}; };
static int reg_w_buf(struct gspca_dev *gspca_dev, static void reg_w_buf(struct gspca_dev *gspca_dev,
__u8 index, __u8 index,
const char *buffer, int len) const char *buffer, int len)
{ {
int ret; int ret;
if (gspca_dev->usb_err < 0)
return;
memcpy(gspca_dev->usb_buf, buffer, len); memcpy(gspca_dev->usb_buf, buffer, len);
ret = usb_control_msg(gspca_dev->dev, ret = usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0), usb_sndctrlpipe(gspca_dev->dev, 0),
...@@ -272,20 +274,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, ...@@ -272,20 +274,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev,
0, /* value */ 0, /* value */
index, gspca_dev->usb_buf, len, index, gspca_dev->usb_buf, len,
500); 500);
if (ret < 0) if (ret < 0) {
PDEBUG(D_ERR, "reg_w_buf(): " PDEBUG(D_ERR, "reg_w_buf(): "
"Failed to write registers to index 0x%x, error %i", "Failed to write registers to index 0x%x, error %i",
index, ret); index, ret);
return ret; gspca_dev->usb_err = ret;
}
} }
static int reg_w(struct gspca_dev *gspca_dev, static void reg_w(struct gspca_dev *gspca_dev,
__u8 index, __u8 index,
__u8 value) __u8 value)
{ {
int ret; int ret;
if (gspca_dev->usb_err < 0)
return;
gspca_dev->usb_buf[0] = value; gspca_dev->usb_buf[0] = value;
ret = usb_control_msg(gspca_dev->dev, ret = usb_control_msg(gspca_dev->dev,
usb_sndctrlpipe(gspca_dev->dev, 0), usb_sndctrlpipe(gspca_dev->dev, 0),
...@@ -293,32 +298,32 @@ static int reg_w(struct gspca_dev *gspca_dev, ...@@ -293,32 +298,32 @@ static int reg_w(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, gspca_dev->usb_buf, 1, 0, index, gspca_dev->usb_buf, 1,
500); 500);
if (ret < 0) if (ret < 0) {
PDEBUG(D_ERR, "reg_w(): " PDEBUG(D_ERR, "reg_w(): "
"Failed to write register to index 0x%x, value 0x%x, error %i", "Failed to write register to index 0x%x, value 0x%x, error %i",
index, value, ret); index, value, ret);
return ret; gspca_dev->usb_err = ret;
}
} }
static int reg_w_seq(struct gspca_dev *gspca_dev, static void reg_w_seq(struct gspca_dev *gspca_dev,
const __u8 *seq, int len) const __u8 *seq, int len)
{ {
int ret = 0;
while (--len >= 0) { while (--len >= 0) {
if (0 <= ret) reg_w(gspca_dev, seq[0], seq[1]);
ret = reg_w(gspca_dev, seq[0], seq[1]);
seq += 2; seq += 2;
} }
return ret;
} }
/* load the beginning of a page */ /* load the beginning of a page */
static int reg_w_page(struct gspca_dev *gspca_dev, static void reg_w_page(struct gspca_dev *gspca_dev,
const __u8 *page, int len) const __u8 *page, int len)
{ {
int index; int index;
int ret = 0; int ret = 0;
if (gspca_dev->usb_err < 0)
return;
for (index = 0; index < len; index++) { for (index = 0; index < len; index++) {
if (page[index] == SKIP) /* skip this index */ if (page[index] == SKIP) /* skip this index */
continue; continue;
...@@ -334,52 +339,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, ...@@ -334,52 +339,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev,
"Failed to write register to index 0x%x, " "Failed to write register to index 0x%x, "
"value 0x%x, error %i", "value 0x%x, error %i",
index, page[index], ret); index, page[index], ret);
gspca_dev->usb_err = ret;
break; break;
} }
} }
return ret;
} }
/* output a variable sequence */ /* output a variable sequence */
static int reg_w_var(struct gspca_dev *gspca_dev, static void reg_w_var(struct gspca_dev *gspca_dev,
const __u8 *seq, const __u8 *seq,
const __u8 *page4, unsigned int page4_len) const __u8 *page4, unsigned int page4_len)
{ {
int index, len; int index, len;
int ret = 0;
for (;;) { for (;;) {
index = *seq++; index = *seq++;
len = *seq++; len = *seq++;
switch (len) { switch (len) {
case END_OF_SEQUENCE: case END_OF_SEQUENCE:
return ret; return;
case LOAD_PAGE4: case LOAD_PAGE4:
ret = reg_w_page(gspca_dev, page4, page4_len); reg_w_page(gspca_dev, page4, page4_len);
break; break;
default: default:
if (len > USB_BUF_SZ) { if (len > USB_BUF_SZ) {
PDEBUG(D_ERR|D_STREAM, PDEBUG(D_ERR|D_STREAM,
"Incorrect variable sequence"); "Incorrect variable sequence");
return -EINVAL; return;
} }
while (len > 0) { while (len > 0) {
if (len < 8) { if (len < 8) {
ret = reg_w_buf(gspca_dev, reg_w_buf(gspca_dev,
index, seq, len); index, seq, len);
if (ret < 0)
return ret;
seq += len; seq += len;
break; break;
} }
ret = reg_w_buf(gspca_dev, index, seq, 8); reg_w_buf(gspca_dev, index, seq, 8);
seq += 8; seq += 8;
index += 8; index += 8;
len -= 8; len -= 8;
} }
} }
if (ret < 0)
return ret;
} }
/* not reached */ /* not reached */
} }
...@@ -407,46 +407,36 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -407,46 +407,36 @@ static int sd_config(struct gspca_dev *gspca_dev,
} }
/* This function is used by pac7311 only */ /* This function is used by pac7311 only */
static int setcontrast(struct gspca_dev *gspca_dev) static void setcontrast(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret;
ret = reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0xff, 0x04);
if (0 <= ret) reg_w(gspca_dev, 0x10, sd->contrast >> 4);
ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4);
/* load registers to sensor (Bit 0, auto clear) */ /* load registers to sensor (Bit 0, auto clear) */
if (0 <= ret) reg_w(gspca_dev, 0x11, 0x01);
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
} }
static int setgain(struct gspca_dev *gspca_dev) static void setgain(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int gain = GAIN_MAX - sd->gain; int gain = GAIN_MAX - sd->gain;
int ret;
if (gain < 1) if (gain < 1)
gain = 1; gain = 1;
else if (gain > 245) else if (gain > 245)
gain = 245; gain = 245;
ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
if (0 <= ret) reg_w(gspca_dev, 0x0e, 0x00);
ret = reg_w(gspca_dev, 0x0e, 0x00); reg_w(gspca_dev, 0x0f, gain);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x0f, gain);
/* load registers to sensor (Bit 0, auto clear) */ /* load registers to sensor (Bit 0, auto clear) */
if (0 <= ret) reg_w(gspca_dev, 0x11, 0x01);
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
} }
static int setexposure(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret;
__u8 reg; __u8 reg;
/* register 2 of frame 3/4 contains the clock divider configuring the /* register 2 of frame 3/4 contains the clock divider configuring the
...@@ -458,93 +448,72 @@ static int setexposure(struct gspca_dev *gspca_dev) ...@@ -458,93 +448,72 @@ static int setexposure(struct gspca_dev *gspca_dev)
else if (reg > 63) else if (reg > 63)
reg = 63; reg = 63;
ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
if (0 <= ret) reg_w(gspca_dev, 0x02, reg);
ret = reg_w(gspca_dev, 0x02, reg);
/* Page 1 register 8 must always be 0x08 except when not in /* Page 1 register 8 must always be 0x08 except when not in
640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0xff, 0x01);
if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
reg <= 3) { reg <= 3) {
if (0 <= ret) reg_w(gspca_dev, 0x08, 0x09);
ret = reg_w(gspca_dev, 0x08, 0x09);
} else { } else {
if (0 <= ret) reg_w(gspca_dev, 0x08, 0x08);
ret = reg_w(gspca_dev, 0x08, 0x08);
} }
/* load registers to sensor (Bit 0, auto clear) */ /* load registers to sensor (Bit 0, auto clear) */
if (0 <= ret) reg_w(gspca_dev, 0x11, 0x01);
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
} }
static int sethvflip(struct gspca_dev *gspca_dev) static void sethvflip(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret;
__u8 data; __u8 data;
ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
if (0 <= ret) reg_w(gspca_dev, 0x21, data);
ret = reg_w(gspca_dev, 0x21, data);
/* load registers to sensor (Bit 0, auto clear) */ /* load registers to sensor (Bit 0, auto clear) */
if (0 <= ret) reg_w(gspca_dev, 0x11, 0x01);
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
} }
/* this function is called at probe and resume time for pac7311 */ /* this function is called at probe and resume time for pac7311 */
static int sd_init(struct gspca_dev *gspca_dev) static int sd_init(struct gspca_dev *gspca_dev)
{ {
return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
return gspca_dev->usb_err;
} }
static int sd_start(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
int ret;
sd->sof_read = 0; sd->sof_read = 0;
ret = reg_w_var(gspca_dev, start_7311, reg_w_var(gspca_dev, start_7311,
page4_7311, sizeof(page4_7311)); page4_7311, sizeof(page4_7311));
if (0 <= ret) setcontrast(gspca_dev);
ret = setcontrast(gspca_dev); setgain(gspca_dev);
if (0 <= ret) setexposure(gspca_dev);
ret = setgain(gspca_dev); sethvflip(gspca_dev);
if (0 <= ret)
ret = setexposure(gspca_dev);
if (0 <= ret)
ret = sethvflip(gspca_dev);
/* set correct resolution */ /* set correct resolution */
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
case 2: /* 160x120 pac7311 */ case 2: /* 160x120 pac7311 */
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x17, 0x20);
if (0 <= ret) reg_w(gspca_dev, 0x87, 0x10);
ret = reg_w(gspca_dev, 0x17, 0x20);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x87, 0x10);
break; break;
case 1: /* 320x240 pac7311 */ case 1: /* 320x240 pac7311 */
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x17, 0x30);
if (0 <= ret) reg_w(gspca_dev, 0x87, 0x11);
ret = reg_w(gspca_dev, 0x17, 0x30);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x87, 0x11);
break; break;
case 0: /* 640x480 */ case 0: /* 640x480 */
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x17, 0x00);
if (0 <= ret) reg_w(gspca_dev, 0x87, 0x12);
ret = reg_w(gspca_dev, 0x17, 0x00);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x87, 0x12);
break; break;
} }
...@@ -553,37 +522,24 @@ static int sd_start(struct gspca_dev *gspca_dev) ...@@ -553,37 +522,24 @@ static int sd_start(struct gspca_dev *gspca_dev)
atomic_set(&sd->avg_lum, -1); atomic_set(&sd->avg_lum, -1);
/* start stream */ /* start stream */
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x05);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x05);
return ret; return gspca_dev->usb_err;
} }
static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev)
{ {
int ret; reg_w(gspca_dev, 0xff, 0x04);
reg_w(gspca_dev, 0x27, 0x80);
ret = reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x28, 0xca);
if (0 <= ret) reg_w(gspca_dev, 0x29, 0x53);
ret = reg_w(gspca_dev, 0x27, 0x80); reg_w(gspca_dev, 0x2a, 0x0e);
if (0 <= ret) reg_w(gspca_dev, 0xff, 0x01);
ret = reg_w(gspca_dev, 0x28, 0xca); reg_w(gspca_dev, 0x3e, 0x20);
if (0 <= ret) reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
ret = reg_w(gspca_dev, 0x29, 0x53); reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
if (0 <= ret) reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
ret = reg_w(gspca_dev, 0x2a, 0x0e);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xff, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x3e, 0x20);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
} }
/* called on streamoff with alt 0 and on disconnect for 7311 */ /* called on streamoff with alt 0 and on disconnect for 7311 */
...@@ -728,7 +684,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) ...@@ -728,7 +684,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 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)
...@@ -746,7 +702,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) ...@@ -746,7 +702,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
sd->gain = val; sd->gain = val;
if (gspca_dev->streaming) if (gspca_dev->streaming)
setgain(gspca_dev); setgain(gspca_dev);
return 0; return gspca_dev->usb_err;
} }
static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
...@@ -764,7 +720,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) ...@@ -764,7 +720,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
sd->exposure = val; sd->exposure = val;
if (gspca_dev->streaming) if (gspca_dev->streaming)
setexposure(gspca_dev); setexposure(gspca_dev);
return 0; return gspca_dev->usb_err;
} }
static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
...@@ -795,7 +751,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) ...@@ -795,7 +751,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
} }
} }
return 0; return gspca_dev->usb_err;
} }
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
...@@ -813,7 +769,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) ...@@ -813,7 +769,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)
...@@ -831,7 +787,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) ...@@ -831,7 +787,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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment