Friday, May 9, 2008

17a1:0128 TASCORP



Driver: gspcav2 ( gspca with v4l2 support, etc,etc)
Driver Base - Homepage: http://moinejf.free.fr ( Michel Xhaard / Jean-François Moine )
Base file: gspcav2-0.1.0.tar.gz
Patch for: Tascorp 17a1:0128 "XPX JPEG Webcam"
Chipset/Bridge: T613 Sensor: TAS5130A
Link to MailList with patch

Download: Patch File

Note: I need testers for this webcam. Also , be sure that chip and sensor is the same on your device. "Webcam Effects" are there for testing purpose only.

UPDATE: Lastest version of gspca2 with t613 subdriver included ( not need to patch ),
can be downloaded from: http://moinejf.free.fr/gspcav2-0.2.0.tar.gz








diff -Nru gspcav2-0.1.0/gspca.h gspcav2-0.1.0-t613/gspca.h
--- gspcav2-0.1.0/gspca.h 2008-04-28 04:58:27.000000000 -0300
+++ gspcav2-0.1.0-t613/gspca.h 2008-05-07 03:43:09.000000000 -0300
@@ -68,6 +68,12 @@
struct gspca_dev;
struct gspca_frame;

+struct control_menu_info
+{
+ int value;
+ char name[32];
+};
+
/* subdriver operations */
typedef int (*cam_op) (struct gspca_dev *);
typedef void (*cam_v_op) (struct gspca_dev *);
diff -Nru gspcav2-0.1.0/Kbuild gspcav2-0.1.0-t613/Kbuild
--- gspcav2-0.1.0/Kbuild 2008-04-12 03:49:59.000000000 -0300
+++ gspcav2-0.1.0-t613/Kbuild 2008-05-07 03:45:02.000000000 -0300
@@ -5,7 +5,7 @@
gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
gspca_sunplus.o gspca_stk014.o gspca_tv8532.o \
- gspca_vc032x.o gspca_zc3xx.o
+ gspca_vc032x.o gspca_zc3xx.o gspca_t613.o
gspca_conex-objs := conex.o
gspca_etoms-objs := etoms.o
gspca_main-objs := gspca.o
@@ -26,3 +26,5 @@
gspca_tv8532-objs := tv8532.o
gspca_vc032x-objs := vc032x.o
gspca_zc3xx-objs := zc3xx.o
+gspca_t613-objs := t613.o
+
diff -Nru gspcav2-0.1.0/Makefile.standalone gspcav2-0.1.0-t613/Makefile.standalone
--- gspcav2-0.1.0/Makefile.standalone 2008-04-29 03:26:09.000000000 -0300
+++ gspcav2-0.1.0-t613/Makefile.standalone 2008-05-07 03:51:06.000000000 -0300
@@ -49,6 +49,7 @@
gspcav2-$(VERSION)/tv8532.c \
gspcav2-$(VERSION)/vc032x.c \
gspcav2-$(VERSION)/webcam.html \
- gspcav2-$(VERSION)/zc3xx.c;
+ gspcav2-$(VERSION)/zc3xx.c \
+ gspcav2-$(VERSION)/t613.c;
rm gspcav2-$(VERSION)

diff -Nru gspcav2-0.1.0/t613.c gspcav2-0.1.0-t613/t613.c
--- gspcav2-0.1.0/t613.c 1969-12-31 21:00:00.000000000 -0300
+++ gspcav2-0.1.0-t613/t613.c 2008-05-08 03:38:53.000000000 -0300
@@ -0,0 +1,1009 @@
+#define MODULE_NAME "t613"
+#include "gspca.h"
+#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 0, 21)
+static const char version[] = "0.0.21";
+#define MAX_GAMMA 0x10 //0 to 15
+
+//From LUVCVIEW
+#define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_PRIVATE_BASE+1)
+#define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE+0)
+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE_AUTO (V4L2_CID_PRIVATE_BASE + 2 )
+#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3 )
+
+
+#define BRIDGE_T16 1
+
+MODULE_AUTHOR("Leandro Costantino ");
+MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance ) USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/*
+ *Notes: * t613 + tas5130A
+ * Focus to light do not balance well as in win. Quality in win is not good, but its kinda better.
+ * * Fix some "extraneous bytes", most of apps will show the image anyway
+ * * Gamma table, is there, but its really doing something?
+ * * 7~8 Fps, its ok, max on win its 10.
+ * Costantino Leandro
+ */
+
+
+
+struct sd
+{
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+
+ unsigned char packet[ISO_MAX_SIZE + 128]; // !! no more than 128 ff in an ISO packet
+
+ unsigned char brightness;
+ unsigned char contrast;
+ unsigned char colors;
+ unsigned char autogain;
+ unsigned char gamma;
+ unsigned char sharpness;
+ unsigned char freq;
+ unsigned char whitebalance;
+ unsigned char mirror;
+ unsigned char effect;
+ char qindex;
+ char bridge;
+ char subtype;
+
+};
+
+/* 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_setcolors(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgamma(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 int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_querymenu (struct gspca_dev *gspca_dev,struct v4l2_querymenu *menu);
+
+
+//just in case someone need to pass it as mod parameter, and use it as in vmicro/ztar module, function its already here
+static void setlightfreq(struct gspca_dev *gspca_dev);
+
+static struct ctrl sd_ctrls[] =
+{
+#define SD_BRIGHTNESS 0
+ {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 0xf,
+ .step = 1,
+ .default_value = 0x9,
+ },
+ .set = sd_setbrightness,
+ .get = sd_getbrightness,
+ },
+#define SD_CONTRAST 1
+ {
+ {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 0xD,
+ .step = 1,
+ .default_value = 0x7,
+ },
+ .set = sd_setcontrast,
+ .get = sd_getcontrast,
+ },
+#define SD_COLOR 2
+ {
+ {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Color",
+ .minimum = 0,
+ .maximum = 0xF,
+ .step = 1,
+ .default_value = 0x5,
+ },
+ .set = sd_setcolors,
+ .get = sd_getcolors,
+ },
+#define SD_AUTOGAIN 3
+
+ {
+ {
+ .id = V4L2_CID_GAIN, //here, i activate only the lowlight, some apps dont bring up the backligth_compensation control)
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Low Light",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0x1,
+ },
+ .set = sd_setlowlight,
+ .get = sd_getlowlight,
+ },
+#define SD_GAMMA 4
+ {
+ {
+ .id = V4L2_CID_GAMMA, //(gamma on win )
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gamma ( Untested )",
+ .minimum = 0,
+ .maximum = MAX_GAMMA,
+ .step = 1,
+ .default_value = 0x9,
+ },
+ .set = sd_setgamma,
+ .get = sd_getgamma,
+ },
+#define SD_SHARPNESS 5 // (aka definition on win )
+ {
+ {
+ .id = V4L2_CID_SHARPNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Sharpness",
+ .minimum = 0,
+ .maximum = MAX_GAMMA , //0 to 16
+ .step = 1,
+ .default_value = 0x6,
+ },
+ .set = sd_setsharpness,
+ .get = sd_getsharpness,
+ },
+#define SD_LIGHTFREQ 6
+ {
+ {
+ .id = V4L2_CID_POWER_LINE_FREQUENCY,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Light Frequency Filter",
+ .minimum = 0, //0 -> 0x50, 1->0x60
+ .maximum = 1 ,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setfreq,
+ .get = sd_getfreq
+ },
+
+#define SD_WHITE_BALANCE 7
+ {
+ {
+ .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE_AUTO,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "White Balance",
+ .minimum = 0,
+ .maximum = 1 ,
+ .step = 1,
+ .default_value = 1,
+ },
+ .set = sd_setwhitebalance,
+ .get = sd_getwhitebalance
+ },
+#define SD_MIRROR 8
+ {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror Image",
+ .minimum = 0,
+ .maximum = 1 ,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_setflip,
+ .get = sd_getflip
+ },
+
+#define SD_EFFECTS 8
+ {
+ {
+ .id = V4L2_CID_EFFECTS,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "Webcam Effects",
+ .minimum = 0,
+ .maximum = 4 ,
+ .step = 1,
+ .default_value = 0,
+ },
+ .set = sd_seteffect,
+ .get = sd_geteffect
+ },
+
+};
+
+static struct control_menu_info flicker_control[] =
+{
+ { 0, "50 Hz" },
+ { 1, "60 Hz" },
+
+};
+#define NUM_FLICKER_CONTROL (sizeof(flicker_control)/sizeof(flicker_control[0]))
+static struct control_menu_info effects_control[] =
+{
+ { 0, "Normal" },
+ { 1, "Emboss" }, //disabled
+ { 2, "Monochrome" },
+ { 3, "Sepia" },
+ { 4, "Sketch" },
+ { 5, "Sun Effect" }, //disabled
+ { 6, "Negative" },
+};
+#define NUM_EFFECTS_CONTROL (sizeof(effects_control)/sizeof(effects_control[0]))
+
+
+static struct cam_mode vga_mode_t16[]=
+{
+ {V4L2_PIX_FMT_JPEG, 160, 120, 4},
+ {V4L2_PIX_FMT_JPEG, 176, 144, 3},
+ {V4L2_PIX_FMT_JPEG, 320, 240, 2},
+ {V4L2_PIX_FMT_JPEG, 352, 288, 1},
+ {V4L2_PIX_FMT_JPEG, 640, 480, 0},
+
+}
+;
+#define T16_OFFSET_DATA 631
+#define MAX_EFFECTS 7
+/* easily done by soft, this table could be removed, i keep it here just in case */
+unsigned char effects_table[MAX_EFFECTS][6]=
+{
+ {0xa8,0xe8,0xc6,0xd2,0xc0,0x00}, //Normal
+ {0xa8,0xc8,0xc6,0x52,0xc0,0x04},//Repujar
+ {0xa8,0xe8,0xc6,0xd2,0xc0,0x20}, //Monochrome
+ {0xa8,0xe8,0xc6,0xd2,0xc0,0x80}, //Sepia
+ {0xa8,0xc8,0xc6,0x52,0xc0,0x02}, //Croquis
+ {0xa8,0xc8,0xc6,0xd2,0xc0,0x10}, //Sun Effect
+ {0xa8,0xc8,0xc6,0xd2,0xc0,0x40}, //Negative
+};
+
+
+
+unsigned char gamma_table[MAX_GAMMA][34]=
+{
+ {0x90 ,0x00 ,0x91 ,0x3e ,0x92 ,0x69 ,0x93 ,0x85 ,0x94 ,0x95 ,0x95 ,0xa1 ,0x96 ,0xae ,0x97 ,0xb9 ,0x98 ,0xc2 ,0x99 ,0xcb ,0x9a ,0xd4 ,0x9b ,0xdb ,0x9c ,0xe3 ,0x9d ,0xea ,0x9e ,0xf1 ,0x9f ,0xf8 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x33 ,0x92 ,0x5A ,0x93 ,0x75 ,0x94 ,0x85 ,0x95 ,0x93 ,0x96 ,0xA1 ,0x97 ,0xAD ,0x98 ,0xB7 ,0x99 ,0xC2 ,0x9A ,0xCB ,0x9B ,0xD4 ,0x9C ,0xDE ,0x9D ,0xE7 ,0x9E ,0xF0 ,0x9F ,0xF7 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x2F ,0x92 ,0x51 ,0x93 ,0x6B ,0x94 ,0x7C ,0x95 ,0x8A ,0x96 ,0x99 ,0x97 ,0xA6 ,0x98 ,0xB1 ,0x99 ,0xBC ,0x9A ,0xC6 ,0x9B ,0xD0 ,0x9C ,0xDB ,0x9D ,0xE4 ,0x9E ,0xED ,0x9F ,0xF6 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x29 ,0x92 ,0x48 ,0x93 ,0x60 ,0x94 ,0x72 ,0x95 ,0x81 ,0x96 ,0x90 ,0x97 ,0x9E ,0x98 ,0xAA ,0x99 ,0xB5 ,0x9A ,0xBF ,0x9B ,0xCB ,0x9C ,0xD6 ,0x9D ,0xE1 ,0x9E ,0xEB ,0x9F ,0xF5 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x23 ,0x92 ,0x3F ,0x93 ,0x55 ,0x94 ,0x68 ,0x95 ,0x77 ,0x96 ,0x86 ,0x97 ,0x95 ,0x98 ,0xA2 ,0x99 ,0xAD ,0x9A ,0xB9 ,0x9B ,0xC6 ,0x9C ,0xD2 ,0x9D ,0xDE ,0x9E ,0xE9 ,0x9F ,0xF4 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x1B ,0x92 ,0x33 ,0x93 ,0x48 ,0x94 ,0x59 ,0x95 ,0x69 ,0x96 ,0x79 ,0x97 ,0x87 ,0x98 ,0x96 ,0x99 ,0xA3 ,0x9A ,0xB1 ,0x9B ,0xBE ,0x9C ,0xCC ,0x9D ,0xDA ,0x9E ,0xE7 ,0x9F ,0xF3 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x02 ,0x92 ,0x10 ,0x93 ,0x20 ,0x94 ,0x32 ,0x95 ,0x40 ,0x96 ,0x57 ,0x97 ,0x67 ,0x98 ,0x77 ,0x99 ,0x88 ,0x9a ,0x99 ,0x9b ,0xaa ,0x9c ,0xbb ,0x9d ,0xcc ,0x9e ,0xdd ,0x9f ,0xee ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x02 ,0x92 ,0x14 ,0x93 ,0x26 ,0x94 ,0x38 ,0x95 ,0x4A ,0x96 ,0x60 ,0x97 ,0x70 ,0x98 ,0x80 ,0x99 ,0x90 ,0x9A ,0xA0 ,0x9B ,0xB0 ,0x9C ,0xC0 ,0x9D ,0xD0 ,0x9E ,0xE0 ,0x9F ,0xF0 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x10 ,0x92 ,0x22 ,0x93 ,0x35 ,0x94 ,0x47 ,0x95 ,0x5A ,0x96 ,0x69 ,0x97 ,0x79 ,0x98 ,0x88 ,0x99 ,0x97 ,0x9A ,0xA7 ,0x9B ,0xB6 ,0x9C ,0xC4 ,0x9D ,0xD3 ,0x9E ,0xE0 ,0x9F ,0xF0 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x10 ,0x92 ,0x26 ,0x93 ,0x40 ,0x94 ,0x54 ,0x95 ,0x65 ,0x96 ,0x75 ,0x97 ,0x84 ,0x98 ,0x93 ,0x99 ,0xa1 ,0x9a ,0xb0 ,0x9b ,0xbd ,0x9c ,0xca ,0x9d ,0xd6 ,0x9e ,0xe0 ,0x9f ,0xf0 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x18 ,0x92 ,0x2B ,0x93 ,0x44 ,0x94 ,0x60 ,0x95 ,0x70 ,0x96 ,0x80 ,0x97 ,0x8E ,0x98 ,0x9C ,0x99 ,0xAA ,0x9A ,0xB7 ,0x9B ,0xC4 ,0x9C ,0xD0 ,0x9D ,0xD8 ,0x9E ,0xE2 ,0x9F ,0xF0 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x1A ,0x92 ,0x34 ,0x93 ,0x52 ,0x94 ,0x66 ,0x95 ,0x7E ,0x96 ,0x8D ,0x97 ,0x9B ,0x98 ,0xA8 ,0x99 ,0xB4 ,0x9A ,0xC0 ,0x9B ,0xCB ,0x9C ,0xD6 ,0x9D ,0xE1 ,0x9E ,0xEB ,0x9F ,0xF5 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x3F ,0x92 ,0x5A ,0x93 ,0x6E ,0x94 ,0x7F ,0x95 ,0x8E ,0x96 ,0x9C ,0x97 ,0xA8 ,0x98 ,0xB4 ,0x99 ,0xBF ,0x9A ,0xC9 ,0x9B ,0xD3 ,0x9C ,0xDC ,0x9D ,0xE5 ,0x9E ,0xEE ,0x9F ,0xF6 ,0xA0 ,0xFF},
+ {0x90 ,0x00 ,0x91 ,0x54 ,0x92 ,0x6F ,0x93 ,0x83 ,0x94 ,0x93 ,0x95 ,0xA0 ,0x96 ,0xAD ,0x97 ,0xB7 ,0x98 ,0xC2 ,0x99 ,0xCB ,0x9A ,0xD4 ,0x9B ,0xDC ,0x9C ,0xE4 ,0x9D ,0xEB ,0x9E ,0xF2 ,0x9F ,0xF9 ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x6E ,0x92 ,0x88 ,0x93 ,0x9A ,0x94 ,0xA8 ,0x95 ,0xB3 ,0x96 ,0xBD ,0x97 ,0xC6 ,0x98 ,0xCF ,0x99 ,0xD6 ,0x9A ,0xDD ,0x9B ,0xE3 ,0x9C ,0xE9 ,0x9D ,0xEF ,0x9E ,0xF4 ,0x9F ,0xFA ,0xa0 ,0xff },
+ {0x90 ,0x00 ,0x91 ,0x93 ,0x92 ,0xA8 ,0x93 ,0xB7 ,0x94 ,0xC1 ,0x95 ,0xCA ,0x96 ,0xD2 ,0x97 ,0xD8 ,0x98 ,0xDE ,0x99 ,0xE3 ,0x9A ,0xE8 ,0x9B ,0xED ,0x9C ,0xF1 ,0x9D ,0xF5 ,0x9E ,0xF8 ,0x9F ,0xFC ,0xA0 ,0xFF}
+}
+;
+
+static __u8 tas5130a_sensor_init[][8]=
+{
+ {0x62,0x08,0x63,0x70,0x64,0x1d,0x60,0x09},
+ {0x62,0x20,0x63,0x01,0x64,0x02,0x60,0x09},
+ {0x62,0x07,0x63,0x03,0x64,0x00,0x60,0x09},
+ {0x62,0x07,0x63,0x03,0x64,0x00,0x60,0x09},
+ {0,0,0,0,0,0,0,0 },
+
+};
+
+static void t16RegRead(struct usb_device *dev,
+ __u16 reg,
+ __u16 value,
+ __u16 index,
+ __u8 *buffer, __u16 length)
+{
+ usb_control_msg(dev,
+ usb_rcvctrlpipe(dev, 0),
+ reg,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ (__u16) value, (__u16) index, buffer, length,
+ 500);
+}
+
+static void t16RegWrite(struct usb_device *dev,
+ __u16 reg,
+ __u16 value,
+ __u16 index,
+ __u8 *buffer, __u16 length)
+{
+ usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ reg,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ (__u16) value, (__u16) index, buffer, length,
+ 500);
+}
+
+/* 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;
+ __u16 vendor;
+ __u16 product;
+
+ vendor = id->idVendor;
+ product = id->idProduct;
+ switch (vendor)
+ {
+ case 0x17a1:
+ //t613 + tas5130A
+ //Currently one sensor supported...
+ sd->freq = 0;
+ sd->bridge = BRIDGE_T16;
+ break;
+
+ default:
+ break;;
+ }
+
+ cam = &gspca_dev->cam;
+ cam->dev_name = (char *) id->driver_info;
+ cam->epaddr = 0x01;
+
+ switch (sd->bridge)
+ {
+
+ default:
+ case BRIDGE_T16:
+ cam->cam_mode = vga_mode_t16;
+ cam->nmodes = sizeof vga_mode_t16 / sizeof vga_mode_t16[0];
+ break;
+
+ }
+ sd->qindex = 4;
+ sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
+ sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
+ sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+ sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
+ sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
+ sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
+ sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
+ sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
+ sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
+ return 0;
+}
+
+static int init_default_parameters( struct gspca_dev * gspca_dev)
+{
+ struct usb_device *dev = gspca_dev->dev;
+
+ /* some of this registers are not really neded, because they are overriden by setbrigthness, setcontrast, etc,
+ * but wont hurt anyway, and can help someone with similar webcam to see the initial parameters.*/
+ int i=0;
+ __u8 test_byte;
+
+ unsigned char read_indexs[]={0x06,0x07,0x0a,0x0b,0x66,0x80,0x81,0x8e,0x8f,0xa5,0xa6,0xa8,0xbb,0xbc,0xc6,0x00,0x00};
+ unsigned char nset[6]={0x61,0xc2,0x65,0x0d,0x60,0x08};
+ unsigned char nset1[50]={
+ 0x80 ,0x3c ,0x81 ,0x68 ,0x83 ,0xa0 ,0x84 ,0x20 ,0x8a ,0x5c ,0x8b ,0x4c ,0x8c ,0x88 ,0x8e ,0xb4,
+ 0x8f ,0x24 ,0xa1 ,0xb1 ,0xa2 ,0x30 ,0xa5 ,0x18 ,0xa6 ,0x4a ,0xae ,0x03 ,0xb1 ,0x44 ,0xb2 ,0x08,
+ 0xb7 ,0x06 ,0xb9 ,0xe7 ,0xbb ,0xc4 ,0xbc ,0x4a ,0xbe ,0x36 ,0xbf ,0xff ,0xc2 ,0x88 ,0xc5 ,0xc0,
+ 0xc6 ,0xd2
+ };
+ unsigned char nset4[18]={
+ 0xe0,0x40,0xe1,0x80,0xe2,0xc0,0xe3,0x41,0xe4,0x81,0xe5,0xc3,0xe6,0x5c,0xe7,0x99,
+ 0xe8,0xe0
+ };
+ //ojo puede ser 0xe6 en vez de 0xe9
+ unsigned char nset2[20]={
+ 0xd0,0xff,0xd1,0xa7,0xd2,0x28,0xd3,0x19,0xd4,0xa0,0xd5,0x07,0xd6,0x04,0xd7,0x62,
+ 0xd8,0xe6,0xd9,0xbc
+ };
+ unsigned char nset3[18]={
+ 0xc7,0x40,0xc8,0x80,0xc9,0xc0,0xca,0x40,0xcb,0x80,0xcc,0xc0,0xcd,0x4d,0xce,0x97,
+ 0xcf,0xe4
+ };
+ unsigned char nset5[4]={0x8f,0x24,0xc3,0x00}; //bright
+ unsigned char nset6[34]={
+ 0x90,0x00,0x91,0x10,0x92,0x26,0x93,0x40,0x94,0x54,0x95,0x65,0x96,0x75,0x97,0x84,
+ 0x98,0x93,0x99,0xa1,0x9a,0xb0,0x9b,0xbd,0x9c,0xca,0x9d,0xd6,0x9e,0xe0,0x9f,0xf0,
+ 0xa0,0xff
+ }; //Gamma
+ unsigned char nset7[4]={0x66,0x00,0xa8,0xe8}; //50/60 Hz
+ unsigned char nset9[4]={0x0b,0x04,0x0a,0x40};
+ unsigned char nset8[6]={0xa8,0xe8,0xc6,0xd2,0xc0,0x00};
+ unsigned char nset10[6]={0x0c,0x03,0xab,0x08,0x81,0x68};
+
+ while( read_indexs[i] != 0x00 )
+ {
+ t16RegRead(dev,0x00,0x00,read_indexs[i], &test_byte,1);
+ PDEBUG( D_CONF, "Reg 0x%x => 0x%x\n",read_indexs[i],test_byte);
+ i++;
+ }
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset,0x06);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset1,0x32);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset2,0x14);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset3,0x12);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset4,0x12);
+ t16RegWrite(dev, 0x00,0x00,0x3c80,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x00,0x3c80,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x00,0xb48e,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x01,00,nset5,0x05);
+ t16RegWrite(dev, 0x00,0x00,0x00a9,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x01,00,nset6,0x22);
+ t16RegWrite(dev, 0x00,0x00,0xc6bb,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x00,0x4aa6,0x00,0x0);
+ // missing write..
+ //t16RegWrite(dev, 0x00,0x01,00,default,0x08);
+ t16RegWrite(dev, 0x00,0x00,0x2087,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x00,0x2088,0x00,0x0);
+ t16RegWrite(dev, 0x00,0x00,0x2089,0x00,0x0);
+
+ t16RegWrite(dev, 0x00,0x01,00,nset7,0x4);
+ t16RegWrite(dev, 0x00,0x01,00,nset10,0x06);
+ t16RegWrite(dev, 0x00,0x01,00,nset8,0x06);
+ t16RegWrite(dev, 0x00,0x01,00,nset9,0x04);
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset2,0x14);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset3,0x12);
+ t16RegWrite(dev, 0x00,0x01,0x0000,nset4,0x12);
+
+ return 0;
+}
+
+
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ unsigned int brightness;
+ unsigned char set6[4]= {0x8f,0x26,0xc3,0x80};
+ brightness = sd->brightness;
+
+ if( brightness < 7 )
+ set6[3]= 0x70 - ( brightness * 0xa);
+ else
+ {
+ set6[1]= 0x24;
+ set6[3]= 0x00 + (( brightness-7) * 0xa);
+ }
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,set6,4);
+}
+
+static void setflip(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+
+ unsigned char flipcmd[8]= {0x62,0x07,0x63,0x03,0x64,0x00,0x60,0x09};
+
+ if( sd->mirror == 1 )
+ flipcmd[3] = 0x01;
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,flipcmd,8);
+
+}
+
+static void seteffect(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+
+ //just in case...
+ if( sd->effect >= MAX_EFFECTS )
+ sd->effect=0;
+
+ t16RegWrite(dev,0x00,0x01,0x0000, effects_table[sd->effect],0x6);
+ if( sd->effect == 1 || sd->effect ==5 )
+ {
+ PDEBUG( D_CONF, "This effect have been disabled for webcam \"safety\"\n");
+ return;
+ }
+
+ if( sd->effect == 1 || sd->effect == 4 )
+ t16RegWrite(dev,0x00,0x00,0x4aa6,0x00,0x00);
+ else
+ t16RegWrite(dev,0x00,0x00,0xfaa6,0x00,0x00);
+
+}
+
+static void setwhitebalance(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+
+ unsigned char white_balance[8]= {0x87,0x20,0x88,0x20,0x89,0x20,0x80,0x38};
+
+ if( sd->whitebalance == 1 )
+ white_balance[7]=0x3c;
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,white_balance,8);
+
+}
+
+static void setlightfreq( struct gspca_dev *gspca_dev )
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ __u8 freq[4] = {0x66,0x40,0xa8,0xe8};
+
+ if( sd->freq == 1 ) //60hz
+ freq[1]= 0x00;
+
+ t16RegWrite(dev,0x00,0x1,0x0000,freq,0x4);
+
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev )
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ unsigned int contrast = sd->contrast;
+ __u16 reg_to_write = 0x00;
+
+ if( contrast < 7 )
+ reg_to_write = 0x8ea9 - (0x200 * contrast);
+ else
+ reg_to_write = ( 0x00a9 + ( (contrast-7) * 0x200 ));
+
+ t16RegWrite(dev,0x00,0x00,reg_to_write,0x00,0);
+
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ __u16 reg_to_write = 0x00;
+
+ reg_to_write = 0xc0bb + (sd->colors * 0x100);
+ t16RegWrite(dev,0x00, 0x00,reg_to_write,0x00,0);
+
+
+}
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+
+ printk( KERN_INFO " Gamma: %d\n", sd->gamma);
+
+ if( sd->gamma >= MAX_GAMMA)
+ sd->gamma = 5;
+
+ t16RegWrite(dev, 0x00,0x01,0x0000, gamma_table[sd->gamma],34);
+
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ __u16 reg_to_write = 0x00;
+ reg_to_write = (0x0aa6) + (0x1000 * sd->sharpness);
+
+ t16RegWrite(dev, 0x00,0x00,reg_to_write, 0x00,0x00);
+
+}
+
+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)
+ setbrightness(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 *val;
+}
+
+
+static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->whitebalance = val;
+ if (gspca_dev->streaming)
+ setwhitebalance(gspca_dev);
+ return 0;
+}
+
+static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->whitebalance;
+ return *val;
+}
+
+
+static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->mirror = val;
+ if (gspca_dev->streaming)
+ setflip(gspca_dev);
+ return 0;
+}
+
+static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->mirror;
+ return *val;
+}
+
+static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+
+ sd->effect = val;
+ if (gspca_dev->streaming)
+ seteffect(gspca_dev);
+ return 0;
+
+}
+
+static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->effect;
+ return *val;
+}
+
+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)
+ setcontrast(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 *val;
+}
+
+static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->colors = val;
+ if (gspca_dev->streaming)
+ setcolors(gspca_dev);
+ return 0;
+}
+
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->colors;
+ return 0;
+}
+
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->gamma = val;
+ if (gspca_dev->streaming)
+ setgamma(gspca_dev);
+
+ return 0;
+}
+
+static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ *val = sd->gamma;
+ return 0;
+}
+
+static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->freq = val;
+ if (gspca_dev->streaming)
+ setlightfreq(gspca_dev);
+ return 0;
+}
+
+static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ *val = sd->freq;
+ 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)
+ setsharpness(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;
+}
+
+/* Low Light set here......*/
+static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+
+ sd->autogain = val;
+ if( val == 1 )
+ t16RegWrite(dev, 0x00,0x00,0xf48e,0x00,0);
+ else
+ t16RegWrite(dev, 0x00,0x00,0xb48e,0x00,0);
+
+ return 0;
+}
+
+static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->autogain;
+ return 0;
+}
+
+static void sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct usb_device *dev = gspca_dev->dev;
+ int mode;
+ __u8 test_byte;
+
+ unsigned char t1[]={0x66,0x00,0xa8,0xe8};
+ unsigned char t2[]={0x07,0x00,0x0d,0x60,0x0e,0x80};
+ unsigned char t3[]={0xb3,0x07,0xb4,0x00,0xb5,0x88,0xb6,0x02,0xb7,0x06,0xb8,0x00,0xb9,0xe7,0xba,0x01};
+ unsigned char t4[]={0x0b,0x04,0x0a,0x40};
+
+ switch( sd->bridge)
+ {
+ default:
+ case BRIDGE_T16:
+ mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
+ switch(mode)
+ {
+ case 1: //352x288
+ t2[1] = 0x40;
+ break;;
+ case 2: //320x240
+ t2[1] = 0x10;
+ break;;
+ case 3: //176x144
+ t2[1] = 0x50;
+ break;;
+ case 4: //160x120
+ t2[1] =0x20;
+ break;;
+ default: //640x480 (0x00)
+ break;;
+ }
+ break;;
+ }
+
+ t16RegWrite(dev, 0x00,0x01,0x0000,tas5130a_sensor_init[0],0x8);
+ t16RegWrite(dev, 0x00,0x01,0x0000,tas5130a_sensor_init[1],0x8);
+ t16RegWrite(dev, 0x00,0x01,0x0000,tas5130a_sensor_init[2],0x8);
+ t16RegWrite(dev, 0x00,0x01,0x0000,tas5130a_sensor_init[3],0x8);
+ t16RegWrite(dev, 0x00,0x00,0x3c80,0x00,0x00);//just in case and to keep sync with logs ( for mine )
+ t16RegWrite(dev, 0x00,0x01,0x0000,tas5130a_sensor_init[3],0x8);
+ t16RegWrite(dev, 0x00,0x00,0x3c80,0x00,0x00);//just in case and to keep sync with logs ( for mine )
+ t16RegWrite(dev, 0x00,0x01,0x0000,t1,4);
+ t16RegWrite(dev, 0x00,0x01,0x0000,t2,6);
+ t16RegRead(dev,0x00,0x00,0x0012,&test_byte,0x1);
+ t16RegWrite(dev, 0x00,0x01,0x0000,t3,0x10);
+ t16RegWrite(dev,0x00,0x00,0x0013,0x00,0x00);
+ t16RegWrite(dev, 0x00,0x01,0x0000,t4,0x4);
+ //restar on each start, just in case, sometimes regs goes wrong when using controls from app
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ setcolors( gspca_dev);
+ seteffect(gspca_dev);
+ setflip( gspca_dev);
+
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+}
+
+static void sd_close(struct gspca_dev *gspca_dev)
+{
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+ struct gspca_frame *frame, // target
+ unsigned char *data, // isoc packet
+ int len) // iso packet length
+{
+ int sof = 0;
+ static unsigned char ffd9[] = {0xff, 0xd9};
+
+
+ if( data[0] == 0x5a )
+ {
+ //Control Packet, after this came the header again, but extra bytes came in the packet before this , sometimes an EOF arrives, sometimes not...
+ return;
+ }
+
+ if( data[len-1] == 0xff && data[len] ==0xd9 )
+ {
+ //Just in case, i have seen packets with the marker, other's do not include it...
+ data+=2;
+ len -=4;
+ }
+
+ else if( data[2] == 0xff && data[3] == 0xd8 )
+ {
+ sof=1;
+ data+=2;
+ len -=2;
+ }
+ else
+ {
+ data += 2;
+ len -= 2;
+ }
+
+ if (sof)
+ {
+ //extra bytes..... , could be processed too but would be a waste of time, right now leave the application and libjpeg do it for ourserlves..
+ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+ ffd9, 2);
+ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len );
+ return;
+ }
+
+ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+ return;
+
+}
+
+static int sd_querymenu (struct gspca_dev *gspca_dev,struct v4l2_querymenu *menu)
+{
+ memset(menu->name,0,sizeof(menu->name));
+
+ switch( menu->id )
+ {
+ case V4L2_CID_POWER_LINE_FREQUENCY:
+
+ if( menu->index < 0 || menu->index >= NUM_FLICKER_CONTROL )
+ return -EINVAL;
+ strncpy(menu->name,flicker_control[menu->index].name,32);
+ break;;
+ case V4L2_CID_EFFECTS:
+ if( menu->index < 0 || menu->index >= NUM_EFFECTS_CONTROL )
+ return -EINVAL;
+ strncpy(menu->name,effects_control[menu->index].name,32);
+ break;;
+ default:
+ break;;
+ };
+
+
+ return 0;
+}
+
+/* this function is called at open time */
+static int sd_open(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ switch (sd->bridge)
+ {
+ case BRIDGE_T16:
+ init_default_parameters(gspca_dev);
+ break;;
+ default:
+ break;;
+
+ }
+ return 0;
+}
+
+/* sub-driver description */
+static struct sd_desc sd_desc =
+{
+ .name = MODULE_NAME,
+ .ctrls = sd_ctrls,
+ .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
+ .config = sd_config,
+ .open = sd_open,
+ .start = sd_start,
+ .stopN = sd_stopN,
+ .stop0 = sd_stop0,
+ .close = sd_close,
+ .pkt_scan = sd_pkt_scan,
+ .querymenu = sd_querymenu,
+};
+
+/* -- module initialisation -- */
+#define DVNM(name) .driver_info = (kernel_ulong_t) name
+static __devinitdata struct usb_device_id device_table[] =
+{
+ {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
+
+ {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ PDEBUG(D_PROBE, "camera probe");
+ return gspca_dev_probe(intf, id, &sd_desc, sizeof (struct sd));
+}
+
+static struct usb_driver sd_driver =
+{
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+};
+
+/* -- module insert / remove -- */
+
+static int __init sd_mod_init(void)
+{
+ if (usb_register(&sd_driver) < 0)
+ return -1;
+ PDEBUG(D_PROBE, "v%s registered", version);
+ 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);
+
+
+

No comments: