unsigned short contrast;
__u8 brightness;
__u8 colors;
+ __u8 blue_balance;
+ __u8 red_balance;
char subtype;
#define Arowana300KCMOSCamera 0
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
#define MY_BRIGHTNESS 0
.minimum = 0,
.maximum = 127,
.step = 1,
- .default_value = 63,
+ .default_value = 0,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 0xffff,
+ .maximum = 64725,
.step = 1,
- .default_value = 0xaa00,
+ .default_value = 64725,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
.minimum = 0,
.maximum = 63,
.step = 1,
- .default_value = 31,
+ .default_value = 20,
},
.set = sd_setcolors,
.get = sd_getcolors,
},
+#define MY_BLUE_BALANCE 3
+ {
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setblue_balance,
+ .get = sd_getblue_balance,
+ },
+#define MY_RED_BALANCE 4
+ {
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = 0,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setred_balance,
+ .get = sd_getred_balance,
+ },
};
-static struct v4l2_pix_format vga_mode[] = {
+static const struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
{}
};
-/* Unknow camera from Ori Usbid 0x0000:0x0000 */
+/* Unknown camera from Ori Usbid 0x0000:0x0000 */
/* Based on snoops from Ori Cohen */
static const __u16 spca501c_mysterious_open_data[][3] = {
{0x02, 0x000f, 0x0005},
return ret;
}
-/* returns: negative is error, pos or zero is data */
-static int reg_read(struct gspca_dev *gspca_dev,
- __u16 req, /* bRequest */
- __u16 index, /* wIndex */
- __u16 length) /* wLength (1 or 2 only) */
-{
- int ret;
-
- gspca_dev->usb_buf[1] = 0;
- ret = usb_control_msg(gspca_dev->dev,
- usb_rcvctrlpipe(gspca_dev->dev, 0),
- req,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, /* value */
- index,
- gspca_dev->usb_buf, length,
- 500); /* timeout */
- if (ret < 0) {
- PDEBUG(D_ERR, "reg_read err %d", ret);
- return -1;
- }
- return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
-}
static int write_vector(struct gspca_dev *gspca_dev,
const __u16 data[][3])
{
struct sd *sd = (struct sd *) gspca_dev;
- reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->brightness);
reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
- reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->brightness);
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u16 brightness;
-
- brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x11, 2);
- sd->brightness = brightness << 1;
}
static void setcontrast(struct gspca_dev *gspca_dev)
sd->contrast & 0xff);
}
-static void getcontrast(struct gspca_dev *gspca_dev)
+static void setcolors(struct gspca_dev *gspca_dev)
{
-/* spca50x->contrast = 0xaa01; */
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
}
-static void setcolors(struct gspca_dev *gspca_dev)
+static void setblue_balance(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
+ reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->blue_balance);
}
-static void getcolors(struct gspca_dev *gspca_dev)
+static void setred_balance(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- sd->colors = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x0c, 2);
-/* sd->hue = (reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x13, */
-/* 2) & 0xFF) << 8; */
+ reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->red_balance);
}
/* this function is called at probe time */
struct cam *cam;
cam = &gspca_dev->cam;
- cam->epaddr = 0x01;
cam->cam_mode = vga_mode;
- cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+ cam->nmodes = ARRAY_SIZE(vga_mode);
sd->subtype = id->driver_info;
sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
+ return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
switch (sd->subtype) {
case Arowana300KCMOSCamera:
case SmileIntlCamera:
goto error;
break;
case MystFromOriUnknownCamera:
- /* UnKnow Ori CMOS Camera data */
+ /* Unknown Ori CMOS Camera data */
if (write_vector(gspca_dev, spca501c_mysterious_open_data))
goto error;
break;
goto error;
break;
}
+ PDEBUG(D_STREAM, "Initializing SPCA501 finished");
return 0;
error:
return -EINVAL;
}
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ int mode;
switch (sd->subtype) {
case ThreeComHomeConnectLite:
write_vector(gspca_dev, spca501c_arowana_open_data);
break;
case MystFromOriUnknownCamera:
- /* UnKnow CMOS Camera data */
+ /* Unknown CMOS Camera data */
write_vector(gspca_dev, spca501c_mysterious_init_data);
break;
default:
/* Generic 501 open data */
write_vector(gspca_dev, spca501_open_data);
}
- PDEBUG(D_STREAM, "Initializing SPCA501 finished");
- return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
- struct usb_device *dev = gspca_dev->dev;
- int mode;
/* memorize the wanted pixel format */
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
}
+/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ if (!gspca_dev->present)
+ return;
reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
}
{
struct sd *sd = (struct sd *) gspca_dev;
- getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
{
struct sd *sd = (struct sd *) gspca_dev;
- getcontrast(gspca_dev);
*val = sd->contrast;
return 0;
}
{
struct sd *sd = (struct sd *) gspca_dev;
- getcolors(gspca_dev);
*val = sd->colors;
return 0;
}
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->blue_balance = val;
+ if (gspca_dev->streaming)
+ setblue_balance(gspca_dev);
+ return 0;
+}
+
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->blue_balance;
+ return 0;
+}
+
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->red_balance = val;
+ if (gspca_dev->streaming)
+ setred_balance(gspca_dev);
+ return 0;
+}
+
+static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->red_balance;
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
- if (usb_register(&sd_driver) < 0)
- return -1;
+ int ret;
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
PDEBUG(D_PROBE, "registered");
return 0;
}