android_kernel_xiaomi_sm8350/drivers/media/video/gspca/xirlink_cit.c

1766 lines
51 KiB
C
Raw Normal View History

/*
* USB IBM C-It Video Camera driver
*
* Supports Xirlink C-It Video Camera, IBM PC Camera,
* IBM NetCamera and Veo Stingray.
*
* Copyright (C) 2010 Hans de Goede <hdgoede@redhat.com>
*
* This driver is based on earlier work of:
*
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Randy Dunlap
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define MODULE_NAME "xirlink-cit"
#include "gspca.h"
MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>");
MODULE_DESCRIPTION("Xirlink C-IT");
MODULE_LICENSE("GPL");
/* FIXME we should autodetect this */
static int ibm_netcam_pro;
module_param(ibm_netcam_pro, int, 0);
MODULE_PARM_DESC(ibm_netcam_pro,
"Use IBM Netcamera Pro init sequences for Model 3 cams");
/* FIXME this should be handled through the V4L2 input selection API */
static int rca_input;
module_param(rca_input, int, 0644);
MODULE_PARM_DESC(rca_input,
"Use rca input instead of ccd sensor on Model 3 cams");
/* specific webcam descriptor */
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
u8 model;
#define CIT_MODEL1 0 /* The model 1 - 4 nomenclature comes from the old */
#define CIT_MODEL2 1 /* ibmcam driver */
#define CIT_MODEL3 2
#define CIT_MODEL4 3
#define CIT_IBM_NETCAM_PRO 4
u8 input_index;
u8 sof_read;
u8 contrast;
u8 brightness;
u8 hue;
u8 sharpness;
};
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
static void sd_stop0(struct gspca_dev *gspca_dev);
static const struct ctrl sd_ctrls[] = {
#define SD_BRIGHTNESS 0
{
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0x0c,
.maximum = 0x3f,
.step = 1,
#define BRIGHTNESS_DEFAULT 0x20
.default_value = BRIGHTNESS_DEFAULT,
.flags = 0,
},
.set = sd_setbrightness,
.get = sd_getbrightness,
},
#define SD_CONTRAST 1
{
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "contrast",
.minimum = 0,
.maximum = 20,
.step = 1,
#define CONTRAST_DEFAULT 10
.default_value = CONTRAST_DEFAULT,
.flags = 0,
},
.set = sd_setcontrast,
.get = sd_getcontrast,
},
#define SD_HUE 2
{
{
.id = V4L2_CID_HUE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Hue",
.minimum = 0x05,
.maximum = 0x37,
.step = 1,
#define HUE_DEFAULT 0x20
.default_value = HUE_DEFAULT,
.flags = 0,
},
.set = sd_sethue,
.get = sd_gethue,
},
#define SD_SHARPNESS 3
{
{
.id = V4L2_CID_SHARPNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Sharpness",
.minimum = 0,
.maximum = 6,
.step = 1,
#define SHARPNESS_DEFAULT 3
.default_value = SHARPNESS_DEFAULT,
.flags = 0,
},
.set = sd_setsharpness,
.get = sd_getsharpness,
},
};
static const struct v4l2_pix_format vga_yuv_mode[] = {
{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
{320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
{640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 640,
.sizeimage = 640 * 480 * 3 / 2,
.colorspace = V4L2_COLORSPACE_SRGB},
};
/*
* 01.01.08 - Added for RCA video in support -LO
* This struct is used to init the Model3 cam to use the RCA video in port
* instead of the CCD sensor.
*/
static const u16 rca_initdata[][3] = {
{0, 0x0000, 0x010c},
{0, 0x0006, 0x012c},
{0, 0x0078, 0x012d},
{0, 0x0046, 0x012f},
{0, 0xd141, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfea8, 0x0124},
{1, 0x0000, 0x0116},
{0, 0x0064, 0x0116},
{1, 0x0000, 0x0115},
{0, 0x0003, 0x0115},
{0, 0x0008, 0x0123},
{0, 0x0000, 0x0117},
{0, 0x0000, 0x0112},
{0, 0x0080, 0x0100},
{0, 0x0000, 0x0100},
{1, 0x0000, 0x0116},
{0, 0x0060, 0x0116},
{0, 0x0002, 0x0112},
{0, 0x0000, 0x0123},
{0, 0x0001, 0x0117},
{0, 0x0040, 0x0108},
{0, 0x0019, 0x012c},
{0, 0x0040, 0x0116},
{0, 0x000a, 0x0115},
{0, 0x000b, 0x0115},
{0, 0x0078, 0x012d},
{0, 0x0046, 0x012f},
{0, 0xd141, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfea8, 0x0124},
{0, 0x0064, 0x0116},
{0, 0x0000, 0x0115},
{0, 0x0001, 0x0115},
{0, 0xffff, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00aa, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xffff, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00f2, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x000f, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xffff, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00f8, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00fc, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xffff, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00f9, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x003c, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xffff, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0027, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0019, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0021, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0006, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0045, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002a, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x000e, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002b, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00f4, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002c, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0004, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002d, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0014, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002e, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0003, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x002f, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0003, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0014, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0053, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0x0000, 0x0101},
{0, 0x00a0, 0x0103},
{0, 0x0078, 0x0105},
{0, 0x0000, 0x010a},
{0, 0x0024, 0x010b},
{0, 0x0028, 0x0119},
{0, 0x0088, 0x011b},
{0, 0x0002, 0x011d},
{0, 0x0003, 0x011e},
{0, 0x0000, 0x0129},
{0, 0x00fc, 0x012b},
{0, 0x0008, 0x0102},
{0, 0x0000, 0x0104},
{0, 0x0008, 0x011a},
{0, 0x0028, 0x011c},
{0, 0x0021, 0x012a},
{0, 0x0000, 0x0118},
{0, 0x0000, 0x0132},
{0, 0x0000, 0x0109},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0031, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x00dc, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0032, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0020, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0001, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0040, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0037, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0030, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0xfff9, 0x0124},
{0, 0x0086, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0038, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0008, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0x0000, 0x0127},
{0, 0xfff8, 0x0124},
{0, 0xfffd, 0x0124},
{0, 0xfffa, 0x0124},
{0, 0x0003, 0x0111},
};
static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
{
struct usb_device *udev = gspca_dev->dev;
int err;
err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
value, index, NULL, 0, 1000);
if (err < 0)
PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
" value 0x%02X, error %d)", index, value, err);
return 0;
}
static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index)
{
struct usb_device *udev = gspca_dev->dev;
__u8 *buf = gspca_dev->usb_buf;
int res;
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
0x00, index, buf, 8, 1000);
if (res < 0) {
PDEBUG(D_ERR,
"Failed to read a register (index 0x%04X, error %d)",
index, res);
return res;
}
PDEBUG(D_PROBE,
"Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x",
index,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
return 0;
}
/*
* ibmcam_model3_Packet1()
*
* 00_0078_012d
* 00_0097_012f
* 00_d141_0124
* 00_0096_0127
* 00_fea8_0124
*/
static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
{
cit_write_reg(gspca_dev, 0x0078, 0x012d);
cit_write_reg(gspca_dev, v1, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, v2, 0x0127);
cit_write_reg(gspca_dev, 0xfea8, 0x0124);
}
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam;
sd->model = id->driver_info;
if (sd->model == CIT_MODEL3 && ibm_netcam_pro)
sd->model = CIT_IBM_NETCAM_PRO;
cam = &gspca_dev->cam;
switch (sd->model) {
case CIT_MODEL3:
cam->cam_mode = vga_yuv_mode;
cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
gspca_dev->ctrl_dis = (1 << SD_HUE);
break;
case CIT_IBM_NETCAM_PRO:
cam->cam_mode = vga_yuv_mode;
cam->nmodes = 2; /* no 640 x 480 */
cam->input_flags = V4L2_IN_ST_VFLIP;
gspca_dev->ctrl_dis = ~(1 << SD_CONTRAST);
break;
}
sd->brightness = BRIGHTNESS_DEFAULT;
sd->contrast = CONTRAST_DEFAULT;
sd->hue = HUE_DEFAULT;
sd->sharpness = SHARPNESS_DEFAULT;
return 0;
}
static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
{
cit_read_reg(gspca_dev, 0x128);
cit_write_reg(gspca_dev, 0x0003, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0100);
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x0000, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0123);
cit_write_reg(gspca_dev, 0x0001, 0x0117);
cit_write_reg(gspca_dev, 0x0040, 0x0108);
cit_write_reg(gspca_dev, 0x0019, 0x012c);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0115);
cit_write_reg(gspca_dev, 0x000b, 0x0115);
cit_write_reg(gspca_dev, 0x0078, 0x012d);
cit_write_reg(gspca_dev, 0x0001, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0079, 0x012d);
cit_write_reg(gspca_dev, 0x00ff, 0x0130);
cit_write_reg(gspca_dev, 0xcd41, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_read_reg(gspca_dev, 0x0126);
cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
cit_model3_Packet1(gspca_dev, 0x000b, 0x0000);
cit_model3_Packet1(gspca_dev, 0x000c, 0x0008);
cit_model3_Packet1(gspca_dev, 0x000d, 0x003a);
cit_model3_Packet1(gspca_dev, 0x000e, 0x0060);
cit_model3_Packet1(gspca_dev, 0x000f, 0x0060);
cit_model3_Packet1(gspca_dev, 0x0010, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0011, 0x0004);
cit_model3_Packet1(gspca_dev, 0x0012, 0x0028);
cit_model3_Packet1(gspca_dev, 0x0013, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0014, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb);
cit_model3_Packet1(gspca_dev, 0x0016, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0017, 0x0037);
cit_model3_Packet1(gspca_dev, 0x0018, 0x0036);
cit_model3_Packet1(gspca_dev, 0x001e, 0x0000);
cit_model3_Packet1(gspca_dev, 0x001f, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1);
cit_model3_Packet1(gspca_dev, 0x0021, 0x0034);
cit_model3_Packet1(gspca_dev, 0x0022, 0x0034);
cit_model3_Packet1(gspca_dev, 0x0025, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0028, 0x0022);
cit_model3_Packet1(gspca_dev, 0x0029, 0x000a);
cit_model3_Packet1(gspca_dev, 0x002b, 0x0000);
cit_model3_Packet1(gspca_dev, 0x002c, 0x0000);
cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x0032, 0x0007);
cit_model3_Packet1(gspca_dev, 0x0033, 0x0005);
cit_model3_Packet1(gspca_dev, 0x0037, 0x0040);
cit_model3_Packet1(gspca_dev, 0x0039, 0x0000);
cit_model3_Packet1(gspca_dev, 0x003a, 0x0000);
cit_model3_Packet1(gspca_dev, 0x003b, 0x0001);
cit_model3_Packet1(gspca_dev, 0x003c, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0040, 0x000c);
cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb);
cit_model3_Packet1(gspca_dev, 0x0042, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0043, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0045, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0048, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff);
cit_model3_Packet1(gspca_dev, 0x004f, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0050, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0051, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0055, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0056, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0057, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0058, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0059, 0x0000);
cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);
cit_model3_Packet1(gspca_dev, 0x005d, 0x0022);
cit_model3_Packet1(gspca_dev, 0x005e, 0x003c);
cit_model3_Packet1(gspca_dev, 0x005f, 0x0050);
cit_model3_Packet1(gspca_dev, 0x0060, 0x0044);
cit_model3_Packet1(gspca_dev, 0x0061, 0x0005);
cit_model3_Packet1(gspca_dev, 0x006a, 0x007e);
cit_model3_Packet1(gspca_dev, 0x006f, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0072, 0x001b);
cit_model3_Packet1(gspca_dev, 0x0073, 0x0005);
cit_model3_Packet1(gspca_dev, 0x0074, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0075, 0x001b);
cit_model3_Packet1(gspca_dev, 0x0076, 0x002a);
cit_model3_Packet1(gspca_dev, 0x0077, 0x003c);
cit_model3_Packet1(gspca_dev, 0x0078, 0x0050);
cit_model3_Packet1(gspca_dev, 0x007b, 0x0000);
cit_model3_Packet1(gspca_dev, 0x007c, 0x0011);
cit_model3_Packet1(gspca_dev, 0x007d, 0x0024);
cit_model3_Packet1(gspca_dev, 0x007e, 0x0043);
cit_model3_Packet1(gspca_dev, 0x007f, 0x005a);
cit_model3_Packet1(gspca_dev, 0x0084, 0x0020);
cit_model3_Packet1(gspca_dev, 0x0085, 0x0033);
cit_model3_Packet1(gspca_dev, 0x0086, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0087, 0x0030);
cit_model3_Packet1(gspca_dev, 0x0088, 0x0070);
cit_model3_Packet1(gspca_dev, 0x008b, 0x0008);
cit_model3_Packet1(gspca_dev, 0x008f, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0090, 0x0006);
cit_model3_Packet1(gspca_dev, 0x0091, 0x0028);
cit_model3_Packet1(gspca_dev, 0x0092, 0x005a);
cit_model3_Packet1(gspca_dev, 0x0093, 0x0082);
cit_model3_Packet1(gspca_dev, 0x0096, 0x0014);
cit_model3_Packet1(gspca_dev, 0x0097, 0x0020);
cit_model3_Packet1(gspca_dev, 0x0098, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046);
cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004);
cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007);
cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002);
cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004);
cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8);
cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014);
cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004);
cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020);
cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040);
cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf);
cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008);
cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8);
cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022);
cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028);
cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002);
cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00be, 0x0003);
cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020);
cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040);
cit_model3_Packet1(gspca_dev, 0x0053, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0082, 0x000e);
cit_model3_Packet1(gspca_dev, 0x0083, 0x0020);
cit_model3_Packet1(gspca_dev, 0x0034, 0x003c);
cit_model3_Packet1(gspca_dev, 0x006e, 0x0055);
cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);
cit_model3_Packet1(gspca_dev, 0x0063, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0066, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0067, 0x0006);
cit_model3_Packet1(gspca_dev, 0x006b, 0x0010);
cit_model3_Packet1(gspca_dev, 0x005a, 0x0001);
cit_model3_Packet1(gspca_dev, 0x005b, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0023, 0x0006);
cit_model3_Packet1(gspca_dev, 0x0026, 0x0004);
cit_model3_Packet1(gspca_dev, 0x0036, 0x0069);
cit_model3_Packet1(gspca_dev, 0x0038, 0x0064);
cit_model3_Packet1(gspca_dev, 0x003d, 0x0003);
cit_model3_Packet1(gspca_dev, 0x003e, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014);
cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014);
cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004);
cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001);
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->model) {
case CIT_MODEL3:
break; /* All is done in sd_start */
case CIT_IBM_NETCAM_PRO:
cit_init_ibm_netcam_pro(gspca_dev);
sd_stop0(gspca_dev);
break;
}
return 0;
}
static int cit_set_brightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
cit_model3_Packet1(gspca_dev, 0x0036, sd->brightness);
break;
case CIT_IBM_NETCAM_PRO:
/* No (known) brightness control for ibm netcam pro */
break;
}
return 0;
}
static int cit_set_contrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
{ /* Preset hardware values */
static const struct {
unsigned short cv1;
unsigned short cv2;
unsigned short cv3;
} cv[7] = {
{ 0x05, 0x05, 0x0f }, /* Minimum */
{ 0x04, 0x04, 0x16 },
{ 0x02, 0x03, 0x16 },
{ 0x02, 0x08, 0x16 },
{ 0x01, 0x0c, 0x16 },
{ 0x01, 0x0e, 0x16 },
{ 0x01, 0x10, 0x16 } /* Maximum */
};
int i = sd->contrast / 3;
cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1);
cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2);
cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3);
break;
}
case CIT_IBM_NETCAM_PRO:
cit_model3_Packet1(gspca_dev, 0x005b, sd->contrast + 1);
break;
}
return 0;
}
static int cit_set_hue(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
/* according to the ibmcam driver this does not work 8/
/* cit_model3_Packet1(gspca_dev, 0x007e, sd->hue); */
break;
case CIT_IBM_NETCAM_PRO:
/* No hue control for ibm netcam pro */
break;
}
return 0;
}
static int cit_set_sharpness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
{ /*
* "Use a table of magic numbers.
* This setting doesn't really change much.
* But that's how Windows does it."
*/
static const struct {
unsigned short sv1;
unsigned short sv2;
unsigned short sv3;
unsigned short sv4;
} sv[7] = {
{ 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */
{ 0x01, 0x04, 0x05, 0x14 },
{ 0x02, 0x04, 0x05, 0x14 },
{ 0x03, 0x04, 0x05, 0x14 },
{ 0x03, 0x05, 0x05, 0x14 },
{ 0x03, 0x06, 0x05, 0x14 },
{ 0x03, 0x07, 0x05, 0x14 } /* Sharpest */
};
cit_model3_Packet1(gspca_dev, 0x0060, sv[sd->sharpness].sv1);
cit_model3_Packet1(gspca_dev, 0x0061, sv[sd->sharpness].sv2);
cit_model3_Packet1(gspca_dev, 0x0062, sv[sd->sharpness].sv3);
cit_model3_Packet1(gspca_dev, 0x0063, sv[sd->sharpness].sv4);
break;
}
case CIT_IBM_NETCAM_PRO:
/* No sharpness setting on ibm netcamera pro */
break;
}
return 0;
}
static int cit_restart_stream(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
cit_write_reg(gspca_dev, 0x0001, 0x0114);
cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
cit_write_reg(gspca_dev, 0x0001, 0x0113);
}
sd->sof_read = 0;
return 0;
}
static int cit_start_model3(struct gspca_dev *gspca_dev)
{
const unsigned short compression = 0; /* 0=none, 7=best frame rate */
int i, clock_div = 0;
/* HDG not in ibmcam driver, added to see if it helps with
auto-detecting between model3 and ibm netcamera pro */
cit_read_reg(gspca_dev, 0x128);
cit_write_reg(gspca_dev, 0x0000, 0x0100);
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x0000, 0x0123);
cit_write_reg(gspca_dev, 0x0001, 0x0117);
cit_write_reg(gspca_dev, 0x0040, 0x0108);
cit_write_reg(gspca_dev, 0x0019, 0x012c);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0115);
cit_write_reg(gspca_dev, 0x0003, 0x0115);
cit_read_reg(gspca_dev, 0x0115);
cit_write_reg(gspca_dev, 0x000b, 0x0115);
/* HDG not in ibmcam driver, added to see if it helps with
auto-detecting between model3 and ibm netcamera pro */
if (0) {
cit_write_reg(gspca_dev, 0x0078, 0x012d);
cit_write_reg(gspca_dev, 0x0001, 0x012f);
cit_write_reg(gspca_dev, 0xd141, 0x0124);
cit_write_reg(gspca_dev, 0x0079, 0x012d);
cit_write_reg(gspca_dev, 0x00ff, 0x0130);
cit_write_reg(gspca_dev, 0xcd41, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_read_reg(gspca_dev, 0x0126);
}
cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6);
cit_model3_Packet1(gspca_dev, 0x000c, 0x0002);
cit_model3_Packet1(gspca_dev, 0x000d, 0x0020);
cit_model3_Packet1(gspca_dev, 0x000e, 0x0033);
cit_model3_Packet1(gspca_dev, 0x000f, 0x0007);
cit_model3_Packet1(gspca_dev, 0x0010, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0011, 0x0070);
cit_model3_Packet1(gspca_dev, 0x0012, 0x0030);
cit_model3_Packet1(gspca_dev, 0x0013, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0014, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0015, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0016, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0017, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0018, 0x0000);
cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3);
cit_model3_Packet1(gspca_dev, 0x0020, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0028, 0x0010);
cit_model3_Packet1(gspca_dev, 0x0029, 0x0054);
cit_model3_Packet1(gspca_dev, 0x002a, 0x0013);
cit_model3_Packet1(gspca_dev, 0x002b, 0x0007);
cit_model3_Packet1(gspca_dev, 0x002d, 0x0028);
cit_model3_Packet1(gspca_dev, 0x002e, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0031, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0032, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0033, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0034, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0035, 0x0038);
cit_model3_Packet1(gspca_dev, 0x003a, 0x0001);
cit_model3_Packet1(gspca_dev, 0x003c, 0x001e);
cit_model3_Packet1(gspca_dev, 0x003f, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0041, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0046, 0x003f);
cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0050, 0x0005);
cit_model3_Packet1(gspca_dev, 0x0052, 0x001a);
cit_model3_Packet1(gspca_dev, 0x0053, 0x0003);
cit_model3_Packet1(gspca_dev, 0x005a, 0x006b);
cit_model3_Packet1(gspca_dev, 0x005d, 0x001e);
cit_model3_Packet1(gspca_dev, 0x005e, 0x0030);
cit_model3_Packet1(gspca_dev, 0x005f, 0x0041);
cit_model3_Packet1(gspca_dev, 0x0064, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0065, 0x0015);
cit_model3_Packet1(gspca_dev, 0x0068, 0x000f);
cit_model3_Packet1(gspca_dev, 0x0079, 0x0000);
cit_model3_Packet1(gspca_dev, 0x007a, 0x0000);
cit_model3_Packet1(gspca_dev, 0x007c, 0x003f);
cit_model3_Packet1(gspca_dev, 0x0082, 0x000f);
cit_model3_Packet1(gspca_dev, 0x0085, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0099, 0x0000);
cit_model3_Packet1(gspca_dev, 0x009b, 0x0023);
cit_model3_Packet1(gspca_dev, 0x009c, 0x0022);
cit_model3_Packet1(gspca_dev, 0x009d, 0x0096);
cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
switch (gspca_dev->width) {
case 160:
cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */
cit_write_reg(gspca_dev, 0x00a9, 0x0119);
cit_write_reg(gspca_dev, 0x0016, 0x011b);
cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
cit_write_reg(gspca_dev, 0x0018, 0x0102);
cit_write_reg(gspca_dev, 0x0004, 0x0104);
cit_write_reg(gspca_dev, 0x0004, 0x011a);
cit_write_reg(gspca_dev, 0x0028, 0x011c);
cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
cit_write_reg(gspca_dev, 0x0000, 0x0118);
cit_write_reg(gspca_dev, 0x0000, 0x0132);
cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
cit_write_reg(gspca_dev, compression, 0x0109);
clock_div = 3;
break;
case 320:
cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */
cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */
cit_write_reg(gspca_dev, 0x0000, 0x011e);
cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
/* 4 commands from 160x120 skipped */
cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
cit_write_reg(gspca_dev, compression, 0x0109);
cit_write_reg(gspca_dev, 0x00d9, 0x0119);
cit_write_reg(gspca_dev, 0x0006, 0x011b);
cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x0010, 0x0104);
cit_write_reg(gspca_dev, 0x0004, 0x011a);
cit_write_reg(gspca_dev, 0x003f, 0x011c);
cit_write_reg(gspca_dev, 0x001c, 0x0118);
cit_write_reg(gspca_dev, 0x0000, 0x0132);
clock_div = 5;
break;
case 640:
cit_write_reg(gspca_dev, 0x00f0, 0x0105);
cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */
cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */
cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */
cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
cit_write_reg(gspca_dev, compression, 0x0109);
cit_write_reg(gspca_dev, 0x0040, 0x0101);
cit_write_reg(gspca_dev, 0x0040, 0x0103);
cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
clock_div = 7;
break;
}
cit_model3_Packet1(gspca_dev, 0x007e, 0x000e); /* Hue */
cit_model3_Packet1(gspca_dev, 0x0036, 0x0011); /* Brightness */
cit_model3_Packet1(gspca_dev, 0x0060, 0x0002); /* Sharpness */
cit_model3_Packet1(gspca_dev, 0x0061, 0x0004); /* Sharpness */
cit_model3_Packet1(gspca_dev, 0x0062, 0x0005); /* Sharpness */
cit_model3_Packet1(gspca_dev, 0x0063, 0x0014); /* Sharpness */
cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
cit_model3_Packet1(gspca_dev, 0x0067, 0x0001); /* Contrast */
cit_model3_Packet1(gspca_dev, 0x005b, 0x000c); /* Contrast */
cit_model3_Packet1(gspca_dev, 0x005c, 0x0016); /* Contrast */
cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
cit_model3_Packet1(gspca_dev, 0x002c, 0x0003); /* Was 1, broke 640x480 */
cit_model3_Packet1(gspca_dev, 0x002f, 0x002a);
cit_model3_Packet1(gspca_dev, 0x0030, 0x0029);
cit_model3_Packet1(gspca_dev, 0x0037, 0x0002);
cit_model3_Packet1(gspca_dev, 0x0038, 0x0059);
cit_model3_Packet1(gspca_dev, 0x003d, 0x002e);
cit_model3_Packet1(gspca_dev, 0x003e, 0x0028);
cit_model3_Packet1(gspca_dev, 0x0078, 0x0005);
cit_model3_Packet1(gspca_dev, 0x007b, 0x0011);
cit_model3_Packet1(gspca_dev, 0x007d, 0x004b);
cit_model3_Packet1(gspca_dev, 0x007f, 0x0022);
cit_model3_Packet1(gspca_dev, 0x0080, 0x000c);
cit_model3_Packet1(gspca_dev, 0x0081, 0x000b);
cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd);
cit_model3_Packet1(gspca_dev, 0x0086, 0x000b);
cit_model3_Packet1(gspca_dev, 0x0087, 0x000b);
cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);
cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0); /* Red sharpness */
cit_model3_Packet1(gspca_dev, 0x0097, 0x0096); /* Blue sharpness */
cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
switch (gspca_dev->width) {
case 160:
cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
cit_model3_Packet1(gspca_dev, 0x0040, 0x000a);
cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
break;
case 320:
cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0051, 0x000b);
break;
case 640:
cit_model3_Packet1(gspca_dev, 0x001f, 0x0002); /* !Same */
cit_model3_Packet1(gspca_dev, 0x0039, 0x003e); /* !Same */
cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
break;
}
/* if (sd->input_index) { */
if (rca_input) {
for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
if (rca_initdata[i][0])
cit_read_reg(gspca_dev, rca_initdata[i][2]);
else
cit_write_reg(gspca_dev, rca_initdata[i][1],
rca_initdata[i][2]);
}
}
return 0;
}
static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
{
const unsigned short compression = 0; /* 0=none, 7=best frame rate */
int i, clock_div = 0;
cit_write_reg(gspca_dev, 0x0003, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0100);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
/* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */
cit_write_reg(gspca_dev, 0x0000, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0123);
cit_write_reg(gspca_dev, 0x0001, 0x0117);
cit_write_reg(gspca_dev, 0x0040, 0x0108);
cit_write_reg(gspca_dev, 0x0019, 0x012c);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
/* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */
cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */
cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
switch (gspca_dev->width) {
case 160:
cit_write_reg(gspca_dev, 0x0024, 0x010b);
cit_write_reg(gspca_dev, 0x0089, 0x0119);
cit_write_reg(gspca_dev, 0x000a, 0x011b);
cit_write_reg(gspca_dev, 0x0003, 0x011e);
cit_write_reg(gspca_dev, 0x0007, 0x0104);
cit_write_reg(gspca_dev, 0x0009, 0x011a);
cit_write_reg(gspca_dev, 0x008b, 0x011c);
cit_write_reg(gspca_dev, 0x0008, 0x0118);
cit_write_reg(gspca_dev, 0x0000, 0x0132);
clock_div = 3;
break;
case 320:
cit_write_reg(gspca_dev, 0x0028, 0x010b);
cit_write_reg(gspca_dev, 0x00d9, 0x0119);
cit_write_reg(gspca_dev, 0x0006, 0x011b);
cit_write_reg(gspca_dev, 0x0000, 0x011e);
cit_write_reg(gspca_dev, 0x000e, 0x0104);
cit_write_reg(gspca_dev, 0x0004, 0x011a);
cit_write_reg(gspca_dev, 0x003f, 0x011c);
cit_write_reg(gspca_dev, 0x000c, 0x0118);
cit_write_reg(gspca_dev, 0x0000, 0x0132);
clock_div = 5;
break;
}
cit_model3_Packet1(gspca_dev, 0x0019, 0x0031);
cit_model3_Packet1(gspca_dev, 0x001a, 0x0003);
cit_model3_Packet1(gspca_dev, 0x001b, 0x0038);
cit_model3_Packet1(gspca_dev, 0x001c, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0024, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0027, 0x0001);
cit_model3_Packet1(gspca_dev, 0x002a, 0x0004);
cit_model3_Packet1(gspca_dev, 0x0035, 0x000b);
cit_model3_Packet1(gspca_dev, 0x003f, 0x0001);
cit_model3_Packet1(gspca_dev, 0x0044, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0054, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001);
cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000);
cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0);
cit_write_reg(gspca_dev, compression, 0x0109);
cit_write_reg(gspca_dev, clock_div, 0x0111);
/* if (sd->input_index) { */
if (rca_input) {
for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
if (rca_initdata[i][0])
cit_read_reg(gspca_dev, rca_initdata[i][2]);
else
cit_write_reg(gspca_dev, rca_initdata[i][1],
rca_initdata[i][2]);
}
}
return 0;
}
/* -- start the camera -- */
static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
struct usb_host_interface *alt;
struct usb_interface *intf;
int packet_size;
switch (sd->model) {
case CIT_MODEL3:
cit_start_model3(gspca_dev);
break;
case CIT_IBM_NETCAM_PRO:
cit_start_ibm_netcam_pro(gspca_dev);
break;
}
cit_set_brightness(gspca_dev);
cit_set_contrast(gspca_dev);
cit_set_hue(gspca_dev);
cit_set_sharpness(gspca_dev);
/* Program max isoc packet size, one day we should use this to
allow us to work together with other isoc devices on the same
root hub. */
intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
if (!alt) {
PDEBUG(D_ERR, "Couldn't get altsetting");
return -EIO;
}
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
cit_write_reg(gspca_dev, packet_size >> 8, 0x0106);
cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107);
cit_restart_stream(gspca_dev);
return 0;
}
static void sd_stopN(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
switch (sd->model) {
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
cit_write_reg(gspca_dev, 0x0000, 0x010c);
break;
}
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
/* We cannot use gspca_dev->present here as that is not set when
sd_init gets called and we get called from sd_init */
if (!gspca_dev->dev)
return;
switch (sd->model) {
case CIT_MODEL3:
cit_write_reg(gspca_dev, 0x0006, 0x012c);
cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
cit_read_reg(gspca_dev, 0x0116);
cit_write_reg(gspca_dev, 0x0064, 0x0116);
cit_read_reg(gspca_dev, 0x0115);
cit_write_reg(gspca_dev, 0x0003, 0x0115);
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
cit_write_reg(gspca_dev, 0x0000, 0x0112);
cit_write_reg(gspca_dev, 0x0080, 0x0100);
break;
case CIT_IBM_NETCAM_PRO:
cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff);
cit_write_reg(gspca_dev, 0x0006, 0x012c);
cit_write_reg(gspca_dev, 0x0000, 0x0116);
/* HDG windows does this, but I cannot get the camera
to restart with this without redoing the entire init
sequence which makes switching modes really slow */
/* cit_write_reg(gspca_dev, 0x0006, 0x0115); */
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
cit_write_reg(gspca_dev, 0x0003, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0111);
/* HDG windows does this, but I get a green picture when
restarting the stream after this */
/* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
cit_write_reg(gspca_dev, 0x00c0, 0x0100);
break;
}
}
static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
{
struct sd *sd = (struct sd *) gspca_dev;
int i;
switch (sd->model) {
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
for (i = 0; i < len; i++) {
switch (sd->sof_read) {
case 0:
if (data[i] == 0x00)
sd->sof_read++;
break;
case 1:
if (data[i] == 0xff)
sd->sof_read++;
else
sd->sof_read = 0;
break;
case 2:
sd->sof_read = 0;
if (data[i] != 0xff) {
if (i >= 4)
PDEBUG(D_FRAM,
"header found at offset: %d: %02x %02x 00 ff %02x %02x\n",
i - 2,
data[i - 4],
data[i - 3],
data[i],
data[i + 1]);
return data + i + 2;
}
break;
}
}
break;
}
return NULL;
}
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
u8 *data, int len)
{
unsigned char *sof;
sof = cit_find_sof(gspca_dev, data, len);
if (sof) {
int n;
/* finish decoding current frame */
n = sof - data;
if (n > 4)
n -= 4;
else
n = 0;
gspca_frame_add(gspca_dev, LAST_PACKET,
data, n);
gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
len -= sof - data;
data = sof;
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
if (gspca_dev->streaming) {
sd_stopN(gspca_dev);
cit_set_brightness(gspca_dev);
cit_restart_stream(gspca_dev);
}
return 0;
}
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->brightness;
return 0;
}
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
if (gspca_dev->streaming) {
sd_stopN(gspca_dev);
cit_set_contrast(gspca_dev);
cit_restart_stream(gspca_dev);
}
return 0;
}
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->contrast;
return 0;
}
static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->hue = val;
if (gspca_dev->streaming) {
sd_stopN(gspca_dev);
cit_set_hue(gspca_dev);
cit_restart_stream(gspca_dev);
}
return 0;
}
static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->hue;
return 0;
}
static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->sharpness = val;
if (gspca_dev->streaming) {
sd_stopN(gspca_dev);
cit_set_sharpness(gspca_dev);
cit_restart_stream(gspca_dev);
}
return 0;
}
static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
*val = sd->sharpness;
return 0;
}
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
.ctrls = sd_ctrls,
.nctrls = ARRAY_SIZE(sd_ctrls),
.config = sd_config,
.init = sd_init,
.start = sd_start,
.stopN = sd_stopN,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
};
/* -- module initialisation -- */
static const __devinitdata struct usb_device_id device_table[] = {
{ USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
{ USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
{ USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 },
{ USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
{ USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
{ USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
THIS_MODULE);
}
static struct usb_driver sd_driver = {
.name = MODULE_NAME,
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
#ifdef CONFIG_PM
.suspend = gspca_suspend,
.resume = gspca_resume,
#endif
};
/* -- module insert / remove -- */
static int __init sd_mod_init(void)
{
int ret;
ret = usb_register(&sd_driver);
if (ret < 0)
return ret;
PDEBUG(D_PROBE, "registered");
return 0;
}
static void __exit sd_mod_exit(void)
{
usb_deregister(&sd_driver);
PDEBUG(D_PROBE, "deregistered");
}
module_init(sd_mod_init);
module_exit(sd_mod_exit);