mirror of https://gitee.com/openkylin/linux.git
V4L/DVB: gspca - pac7311: Use usb_err to propagate USB errors
Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
be927befd0
commit
14799f6cf3
|
@ -258,12 +258,14 @@ static const __u8 page4_7311[] = {
|
|||
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,
|
||||
const char *buffer, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (gspca_dev->usb_err < 0)
|
||||
return;
|
||||
memcpy(gspca_dev->usb_buf, buffer, len);
|
||||
ret = usb_control_msg(gspca_dev->dev,
|
||||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||||
|
@ -272,20 +274,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev,
|
|||
0, /* value */
|
||||
index, gspca_dev->usb_buf, len,
|
||||
500);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR, "reg_w_buf(): "
|
||||
"Failed to write registers to index 0x%x, error %i",
|
||||
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 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (gspca_dev->usb_err < 0)
|
||||
return;
|
||||
gspca_dev->usb_buf[0] = value;
|
||||
ret = usb_control_msg(gspca_dev->dev,
|
||||
usb_sndctrlpipe(gspca_dev->dev, 0),
|
||||
|
@ -293,32 +298,32 @@ static int reg_w(struct gspca_dev *gspca_dev,
|
|||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
0, index, gspca_dev->usb_buf, 1,
|
||||
500);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
PDEBUG(D_ERR, "reg_w(): "
|
||||
"Failed to write register to index 0x%x, value 0x%x, error %i",
|
||||
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)
|
||||
{
|
||||
int ret = 0;
|
||||
while (--len >= 0) {
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, seq[0], seq[1]);
|
||||
reg_w(gspca_dev, seq[0], seq[1]);
|
||||
seq += 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int index;
|
||||
int ret = 0;
|
||||
|
||||
if (gspca_dev->usb_err < 0)
|
||||
return;
|
||||
for (index = 0; index < len; index++) {
|
||||
if (page[index] == SKIP) /* skip this index */
|
||||
continue;
|
||||
|
@ -334,52 +339,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev,
|
|||
"Failed to write register to index 0x%x, "
|
||||
"value 0x%x, error %i",
|
||||
index, page[index], ret);
|
||||
gspca_dev->usb_err = ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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 *page4, unsigned int page4_len)
|
||||
{
|
||||
int index, len;
|
||||
int ret = 0;
|
||||
|
||||
for (;;) {
|
||||
index = *seq++;
|
||||
len = *seq++;
|
||||
switch (len) {
|
||||
case END_OF_SEQUENCE:
|
||||
return ret;
|
||||
return;
|
||||
case LOAD_PAGE4:
|
||||
ret = reg_w_page(gspca_dev, page4, page4_len);
|
||||
reg_w_page(gspca_dev, page4, page4_len);
|
||||
break;
|
||||
default:
|
||||
if (len > USB_BUF_SZ) {
|
||||
PDEBUG(D_ERR|D_STREAM,
|
||||
"Incorrect variable sequence");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
while (len > 0) {
|
||||
if (len < 8) {
|
||||
ret = reg_w_buf(gspca_dev,
|
||||
reg_w_buf(gspca_dev,
|
||||
index, seq, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
seq += len;
|
||||
break;
|
||||
}
|
||||
ret = reg_w_buf(gspca_dev, index, seq, 8);
|
||||
reg_w_buf(gspca_dev, index, seq, 8);
|
||||
seq += 8;
|
||||
index += 8;
|
||||
len -= 8;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
/* not reached */
|
||||
}
|
||||
|
@ -407,46 +407,36 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
|||
}
|
||||
|
||||
/* 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;
|
||||
int ret;
|
||||
|
||||
ret = reg_w(gspca_dev, 0xff, 0x04);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4);
|
||||
reg_w(gspca_dev, 0xff, 0x04);
|
||||
reg_w(gspca_dev, 0x10, sd->contrast >> 4);
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x11, 0x01);
|
||||
return ret;
|
||||
reg_w(gspca_dev, 0x11, 0x01);
|
||||
}
|
||||
|
||||
static int setgain(struct gspca_dev *gspca_dev)
|
||||
static void setgain(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int gain = GAIN_MAX - sd->gain;
|
||||
int ret;
|
||||
|
||||
if (gain < 1)
|
||||
gain = 1;
|
||||
else if (gain > 245)
|
||||
gain = 245;
|
||||
ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x0e, 0x00);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x0f, gain);
|
||||
reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||||
reg_w(gspca_dev, 0x0e, 0x00);
|
||||
reg_w(gspca_dev, 0x0f, gain);
|
||||
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x11, 0x01);
|
||||
return ret;
|
||||
reg_w(gspca_dev, 0x11, 0x01);
|
||||
}
|
||||
|
||||
static int setexposure(struct gspca_dev *gspca_dev)
|
||||
static void setexposure(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int ret;
|
||||
__u8 reg;
|
||||
|
||||
/* register 2 of frame 3/4 contains the clock divider configuring the
|
||||
|
@ -458,93 +448,72 @@ static int setexposure(struct gspca_dev *gspca_dev)
|
|||
else if (reg > 63)
|
||||
reg = 63;
|
||||
|
||||
ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x02, reg);
|
||||
reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
|
||||
reg_w(gspca_dev, 0x02, reg);
|
||||
|
||||
/* 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 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
|
||||
reg <= 3) {
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x08, 0x09);
|
||||
reg_w(gspca_dev, 0x08, 0x09);
|
||||
} else {
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x08, 0x08);
|
||||
reg_w(gspca_dev, 0x08, 0x08);
|
||||
}
|
||||
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x11, 0x01);
|
||||
return ret;
|
||||
reg_w(gspca_dev, 0x11, 0x01);
|
||||
}
|
||||
|
||||
static int sethvflip(struct gspca_dev *gspca_dev)
|
||||
static void sethvflip(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int ret;
|
||||
__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);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x21, data);
|
||||
reg_w(gspca_dev, 0x21, data);
|
||||
|
||||
/* load registers to sensor (Bit 0, auto clear) */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x11, 0x01);
|
||||
return ret;
|
||||
reg_w(gspca_dev, 0x11, 0x01);
|
||||
}
|
||||
|
||||
/* this function is called at probe and resume time for pac7311 */
|
||||
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)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
int ret;
|
||||
|
||||
sd->sof_read = 0;
|
||||
|
||||
ret = reg_w_var(gspca_dev, start_7311,
|
||||
reg_w_var(gspca_dev, start_7311,
|
||||
page4_7311, sizeof(page4_7311));
|
||||
if (0 <= ret)
|
||||
ret = setcontrast(gspca_dev);
|
||||
if (0 <= ret)
|
||||
ret = setgain(gspca_dev);
|
||||
if (0 <= ret)
|
||||
ret = setexposure(gspca_dev);
|
||||
if (0 <= ret)
|
||||
ret = sethvflip(gspca_dev);
|
||||
setcontrast(gspca_dev);
|
||||
setgain(gspca_dev);
|
||||
setexposure(gspca_dev);
|
||||
sethvflip(gspca_dev);
|
||||
|
||||
/* set correct resolution */
|
||||
switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
|
||||
case 2: /* 160x120 pac7311 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0xff, 0x01);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x17, 0x20);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x87, 0x10);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0x17, 0x20);
|
||||
reg_w(gspca_dev, 0x87, 0x10);
|
||||
break;
|
||||
case 1: /* 320x240 pac7311 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0xff, 0x01);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x17, 0x30);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x87, 0x11);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0x17, 0x30);
|
||||
reg_w(gspca_dev, 0x87, 0x11);
|
||||
break;
|
||||
case 0: /* 640x480 */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0xff, 0x01);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x17, 0x00);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x87, 0x12);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0x17, 0x00);
|
||||
reg_w(gspca_dev, 0x87, 0x12);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -553,37 +522,24 @@ static int sd_start(struct gspca_dev *gspca_dev)
|
|||
atomic_set(&sd->avg_lum, -1);
|
||||
|
||||
/* start stream */
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0xff, 0x01);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x78, 0x05);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0x78, 0x05);
|
||||
|
||||
return ret;
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
|
||||
static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = reg_w(gspca_dev, 0xff, 0x04);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x27, 0x80);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x28, 0xca);
|
||||
if (0 <= ret)
|
||||
ret = reg_w(gspca_dev, 0x29, 0x53);
|
||||
if (0 <= ret)
|
||||
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 */
|
||||
reg_w(gspca_dev, 0xff, 0x04);
|
||||
reg_w(gspca_dev, 0x27, 0x80);
|
||||
reg_w(gspca_dev, 0x28, 0xca);
|
||||
reg_w(gspca_dev, 0x29, 0x53);
|
||||
reg_w(gspca_dev, 0x2a, 0x0e);
|
||||
reg_w(gspca_dev, 0xff, 0x01);
|
||||
reg_w(gspca_dev, 0x3e, 0x20);
|
||||
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||||
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||||
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
|
||||
}
|
||||
|
||||
/* 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)
|
|||
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)
|
||||
|
@ -746,7 +702,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
|
|||
sd->gain = val;
|
||||
if (gspca_dev->streaming)
|
||||
setgain(gspca_dev);
|
||||
return 0;
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
|
||||
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)
|
|||
sd->exposure = val;
|
||||
if (gspca_dev->streaming)
|
||||
setexposure(gspca_dev);
|
||||
return 0;
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
|
||||
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)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return gspca_dev->usb_err;
|
||||
}
|
||||
|
||||
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)
|
|||
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)
|
||||
|
@ -831,7 +787,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)
|
||||
|
|
Loading…
Reference in New Issue