cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spca505.c (18160B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * SPCA505 chip based cameras initialization data
      4 *
      5 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9
     10#define MODULE_NAME "spca505"
     11
     12#include "gspca.h"
     13
     14MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
     15MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
     16MODULE_LICENSE("GPL");
     17
     18/* specific webcam descriptor */
     19struct sd {
     20	struct gspca_dev gspca_dev;		/* !! must be the first item */
     21
     22	u8 subtype;
     23#define IntelPCCameraPro 0
     24#define Nxultra 1
     25};
     26
     27static const struct v4l2_pix_format vga_mode[] = {
     28	{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
     29		.bytesperline = 160,
     30		.sizeimage = 160 * 120 * 3 / 2,
     31		.colorspace = V4L2_COLORSPACE_SRGB,
     32		.priv = 4},
     33	{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
     34		.bytesperline = 176,
     35		.sizeimage = 176 * 144 * 3 / 2,
     36		.colorspace = V4L2_COLORSPACE_SRGB,
     37		.priv = 3},
     38	{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
     39		.bytesperline = 320,
     40		.sizeimage = 320 * 240 * 3 / 2,
     41		.colorspace = V4L2_COLORSPACE_SRGB,
     42		.priv = 2},
     43	{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
     44		.bytesperline = 352,
     45		.sizeimage = 352 * 288 * 3 / 2,
     46		.colorspace = V4L2_COLORSPACE_SRGB,
     47		.priv = 1},
     48	{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
     49		.bytesperline = 640,
     50		.sizeimage = 640 * 480 * 3 / 2,
     51		.colorspace = V4L2_COLORSPACE_SRGB,
     52		.priv = 0},
     53};
     54
     55#define SPCA50X_OFFSET_DATA 10
     56
     57#define SPCA50X_REG_USB 0x02	/* spca505 501 */
     58
     59#define SPCA50X_USB_CTRL 0x00	/* spca505 */
     60#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
     61
     62#define SPCA50X_REG_GLOBAL 0x03	/* spca505 */
     63#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
     64#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
     65
     66#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
     67#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
     68#define SPCA50X_GMISC3_SAA7113RST 0x20	/* Not sure about this one spca505 */
     69
     70/* Image format and compression control */
     71#define SPCA50X_REG_COMPRESS 0x04
     72
     73/*
     74 * Data to initialize a SPCA505. Common to the CCD and external modes
     75 */
     76static const u8 spca505_init_data[][3] = {
     77	/* bmRequest,value,index */
     78	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
     79	/* Sensor reset */
     80	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
     81	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
     82	/* Block USB reset */
     83	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
     84
     85	{0x05, 0x01, 0x10},
     86					/* Maybe power down some stuff */
     87	{0x05, 0x0f, 0x11},
     88
     89	/* Setup internal CCD  ? */
     90	{0x06, 0x10, 0x08},
     91	{0x06, 0x00, 0x09},
     92	{0x06, 0x00, 0x0a},
     93	{0x06, 0x00, 0x0b},
     94	{0x06, 0x10, 0x0c},
     95	{0x06, 0x00, 0x0d},
     96	{0x06, 0x00, 0x0e},
     97	{0x06, 0x00, 0x0f},
     98	{0x06, 0x10, 0x10},
     99	{0x06, 0x02, 0x11},
    100	{0x06, 0x00, 0x12},
    101	{0x06, 0x04, 0x13},
    102	{0x06, 0x02, 0x14},
    103	{0x06, 0x8a, 0x51},
    104	{0x06, 0x40, 0x52},
    105	{0x06, 0xb6, 0x53},
    106	{0x06, 0x3d, 0x54},
    107	{}
    108};
    109
    110/*
    111 * Data to initialize the camera using the internal CCD
    112 */
    113static const u8 spca505_open_data_ccd[][3] = {
    114	/* bmRequest,value,index */
    115	/* Internal CCD data set */
    116	{0x03, 0x04, 0x01},
    117	/* This could be a reset */
    118	{0x03, 0x00, 0x01},
    119
    120	/* Setup compression and image registers. 0x6 and 0x7 seem to be
    121	   related to H&V hold, and are resolution mode specific */
    122		{0x04, 0x10, 0x01},
    123		/* DIFF(0x50), was (0x10) */
    124	{0x04, 0x00, 0x04},
    125	{0x04, 0x00, 0x05},
    126	{0x04, 0x20, 0x06},
    127	{0x04, 0x20, 0x07},
    128
    129	{0x08, 0x0a, 0x00},
    130	/* DIFF (0x4a), was (0xa) */
    131
    132	{0x05, 0x00, 0x10},
    133	{0x05, 0x00, 0x11},
    134	{0x05, 0x00, 0x00},
    135	/* DIFF not written */
    136	{0x05, 0x00, 0x01},
    137	/* DIFF not written */
    138	{0x05, 0x00, 0x02},
    139	/* DIFF not written */
    140	{0x05, 0x00, 0x03},
    141	/* DIFF not written */
    142	{0x05, 0x00, 0x04},
    143	/* DIFF not written */
    144		{0x05, 0x80, 0x05},
    145		/* DIFF not written */
    146		{0x05, 0xe0, 0x06},
    147		/* DIFF not written */
    148		{0x05, 0x20, 0x07},
    149		/* DIFF not written */
    150		{0x05, 0xa0, 0x08},
    151		/* DIFF not written */
    152		{0x05, 0x0, 0x12},
    153		/* DIFF not written */
    154	{0x05, 0x02, 0x0f},
    155	/* DIFF not written */
    156		{0x05, 0x10, 0x46},
    157		/* DIFF not written */
    158		{0x05, 0x8, 0x4a},
    159		/* DIFF not written */
    160
    161	{0x03, 0x08, 0x03},
    162	/* DIFF (0x3,0x28,0x3) */
    163	{0x03, 0x08, 0x01},
    164	{0x03, 0x0c, 0x03},
    165	/* DIFF not written */
    166		{0x03, 0x21, 0x00},
    167		/* DIFF (0x39) */
    168
    169/* Extra block copied from init to hopefully ensure CCD is in a sane state */
    170	{0x06, 0x10, 0x08},
    171	{0x06, 0x00, 0x09},
    172	{0x06, 0x00, 0x0a},
    173	{0x06, 0x00, 0x0b},
    174	{0x06, 0x10, 0x0c},
    175	{0x06, 0x00, 0x0d},
    176	{0x06, 0x00, 0x0e},
    177	{0x06, 0x00, 0x0f},
    178	{0x06, 0x10, 0x10},
    179	{0x06, 0x02, 0x11},
    180	{0x06, 0x00, 0x12},
    181	{0x06, 0x04, 0x13},
    182	{0x06, 0x02, 0x14},
    183	{0x06, 0x8a, 0x51},
    184	{0x06, 0x40, 0x52},
    185	{0x06, 0xb6, 0x53},
    186	{0x06, 0x3d, 0x54},
    187	/* End of extra block */
    188
    189		{0x06, 0x3f, 0x1},
    190		/* Block skipped */
    191	{0x06, 0x10, 0x02},
    192	{0x06, 0x64, 0x07},
    193	{0x06, 0x10, 0x08},
    194	{0x06, 0x00, 0x09},
    195	{0x06, 0x00, 0x0a},
    196	{0x06, 0x00, 0x0b},
    197	{0x06, 0x10, 0x0c},
    198	{0x06, 0x00, 0x0d},
    199	{0x06, 0x00, 0x0e},
    200	{0x06, 0x00, 0x0f},
    201	{0x06, 0x10, 0x10},
    202	{0x06, 0x02, 0x11},
    203	{0x06, 0x00, 0x12},
    204	{0x06, 0x04, 0x13},
    205	{0x06, 0x02, 0x14},
    206	{0x06, 0x8a, 0x51},
    207	{0x06, 0x40, 0x52},
    208	{0x06, 0xb6, 0x53},
    209	{0x06, 0x3d, 0x54},
    210	{0x06, 0x60, 0x57},
    211	{0x06, 0x20, 0x58},
    212	{0x06, 0x15, 0x59},
    213	{0x06, 0x05, 0x5a},
    214
    215	{0x05, 0x01, 0xc0},
    216	{0x05, 0x10, 0xcb},
    217		{0x05, 0x80, 0xc1},
    218		/* */
    219		{0x05, 0x0, 0xc2},
    220		/* 4 was 0 */
    221	{0x05, 0x00, 0xca},
    222		{0x05, 0x80, 0xc1},
    223		/*  */
    224	{0x05, 0x04, 0xc2},
    225	{0x05, 0x00, 0xca},
    226		{0x05, 0x0, 0xc1},
    227		/*  */
    228	{0x05, 0x00, 0xc2},
    229	{0x05, 0x00, 0xca},
    230		{0x05, 0x40, 0xc1},
    231		/* */
    232	{0x05, 0x17, 0xc2},
    233	{0x05, 0x00, 0xca},
    234		{0x05, 0x80, 0xc1},
    235		/* */
    236	{0x05, 0x06, 0xc2},
    237	{0x05, 0x00, 0xca},
    238		{0x05, 0x80, 0xc1},
    239		/* */
    240	{0x05, 0x04, 0xc2},
    241	{0x05, 0x00, 0xca},
    242
    243	{0x03, 0x4c, 0x3},
    244	{0x03, 0x18, 0x1},
    245
    246	{0x06, 0x70, 0x51},
    247	{0x06, 0xbe, 0x53},
    248	{0x06, 0x71, 0x57},
    249	{0x06, 0x20, 0x58},
    250	{0x06, 0x05, 0x59},
    251	{0x06, 0x15, 0x5a},
    252
    253	{0x04, 0x00, 0x08},
    254	/* Compress = OFF (0x1 to turn on) */
    255	{0x04, 0x12, 0x09},
    256	{0x04, 0x21, 0x0a},
    257	{0x04, 0x10, 0x0b},
    258	{0x04, 0x21, 0x0c},
    259	{0x04, 0x05, 0x00},
    260	/* was 5 (Image Type ? ) */
    261	{0x04, 0x00, 0x01},
    262
    263	{0x06, 0x3f, 0x01},
    264
    265	{0x04, 0x00, 0x04},
    266	{0x04, 0x00, 0x05},
    267	{0x04, 0x40, 0x06},
    268	{0x04, 0x40, 0x07},
    269
    270	{0x06, 0x1c, 0x17},
    271	{0x06, 0xe2, 0x19},
    272	{0x06, 0x1c, 0x1b},
    273	{0x06, 0xe2, 0x1d},
    274	{0x06, 0xaa, 0x1f},
    275	{0x06, 0x70, 0x20},
    276
    277	{0x05, 0x01, 0x10},
    278	{0x05, 0x00, 0x11},
    279	{0x05, 0x01, 0x00},
    280	{0x05, 0x05, 0x01},
    281		{0x05, 0x00, 0xc1},
    282		/* */
    283	{0x05, 0x00, 0xc2},
    284	{0x05, 0x00, 0xca},
    285
    286	{0x06, 0x70, 0x51},
    287	{0x06, 0xbe, 0x53},
    288	{}
    289};
    290
    291/*
    292 * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
    293 * SPCA505b chip based cameras initialization data
    294 */
    295/* jfm */
    296#define initial_brightness 0x7f	/* 0x0(white)-0xff(black) */
    297/* #define initial_brightness 0x0	//0x0(white)-0xff(black) */
    298/*
    299 * Data to initialize a SPCA505. Common to the CCD and external modes
    300 */
    301static const u8 spca505b_init_data[][3] = {
    302/* start */
    303	{0x02, 0x00, 0x00},		/* init */
    304	{0x02, 0x00, 0x01},
    305	{0x02, 0x00, 0x02},
    306	{0x02, 0x00, 0x03},
    307	{0x02, 0x00, 0x04},
    308	{0x02, 0x00, 0x05},
    309	{0x02, 0x00, 0x06},
    310	{0x02, 0x00, 0x07},
    311	{0x02, 0x00, 0x08},
    312	{0x02, 0x00, 0x09},
    313	{0x03, 0x00, 0x00},
    314	{0x03, 0x00, 0x01},
    315	{0x03, 0x00, 0x02},
    316	{0x03, 0x00, 0x03},
    317	{0x03, 0x00, 0x04},
    318	{0x03, 0x00, 0x05},
    319	{0x03, 0x00, 0x06},
    320	{0x04, 0x00, 0x00},
    321	{0x04, 0x00, 0x02},
    322	{0x04, 0x00, 0x04},
    323	{0x04, 0x00, 0x05},
    324	{0x04, 0x00, 0x06},
    325	{0x04, 0x00, 0x07},
    326	{0x04, 0x00, 0x08},
    327	{0x04, 0x00, 0x09},
    328	{0x04, 0x00, 0x0a},
    329	{0x04, 0x00, 0x0b},
    330	{0x04, 0x00, 0x0c},
    331	{0x07, 0x00, 0x00},
    332	{0x07, 0x00, 0x03},
    333	{0x08, 0x00, 0x00},
    334	{0x08, 0x00, 0x01},
    335	{0x08, 0x00, 0x02},
    336	{0x06, 0x18, 0x08},
    337	{0x06, 0xfc, 0x09},
    338	{0x06, 0xfc, 0x0a},
    339	{0x06, 0xfc, 0x0b},
    340	{0x06, 0x18, 0x0c},
    341	{0x06, 0xfc, 0x0d},
    342	{0x06, 0xfc, 0x0e},
    343	{0x06, 0xfc, 0x0f},
    344	{0x06, 0x18, 0x10},
    345	{0x06, 0xfe, 0x12},
    346	{0x06, 0x00, 0x11},
    347	{0x06, 0x00, 0x14},
    348	{0x06, 0x00, 0x13},
    349	{0x06, 0x28, 0x51},
    350	{0x06, 0xff, 0x53},
    351	{0x02, 0x00, 0x08},
    352
    353	{0x03, 0x00, 0x03},
    354	{0x03, 0x10, 0x03},
    355	{}
    356};
    357
    358/*
    359 * Data to initialize the camera using the internal CCD
    360 */
    361static const u8 spca505b_open_data_ccd[][3] = {
    362
    363/* {0x02,0x00,0x00}, */
    364	{0x03, 0x04, 0x01},		/* rst */
    365	{0x03, 0x00, 0x01},
    366	{0x03, 0x00, 0x00},
    367	{0x03, 0x21, 0x00},
    368	{0x03, 0x00, 0x04},
    369	{0x03, 0x00, 0x03},
    370	{0x03, 0x18, 0x03},
    371	{0x03, 0x08, 0x01},
    372	{0x03, 0x1c, 0x03},
    373	{0x03, 0x5c, 0x03},
    374	{0x03, 0x5c, 0x03},
    375	{0x03, 0x18, 0x01},
    376
    377/* same as 505 */
    378	{0x04, 0x10, 0x01},
    379	{0x04, 0x00, 0x04},
    380	{0x04, 0x00, 0x05},
    381	{0x04, 0x20, 0x06},
    382	{0x04, 0x20, 0x07},
    383
    384	{0x08, 0x0a, 0x00},
    385
    386	{0x05, 0x00, 0x10},
    387	{0x05, 0x00, 0x11},
    388	{0x05, 0x00, 0x12},
    389	{0x05, 0x6f, 0x00},
    390	{0x05, initial_brightness >> 6, 0x00},
    391	{0x05, (initial_brightness << 2) & 0xff, 0x01},
    392	{0x05, 0x00, 0x02},
    393	{0x05, 0x01, 0x03},
    394	{0x05, 0x00, 0x04},
    395	{0x05, 0x03, 0x05},
    396	{0x05, 0xe0, 0x06},
    397	{0x05, 0x20, 0x07},
    398	{0x05, 0xa0, 0x08},
    399	{0x05, 0x00, 0x12},
    400	{0x05, 0x02, 0x0f},
    401	{0x05, 0x80, 0x14},		/* max exposure off (0=on) */
    402	{0x05, 0x01, 0xb0},
    403	{0x05, 0x01, 0xbf},
    404	{0x03, 0x02, 0x06},
    405	{0x05, 0x10, 0x46},
    406	{0x05, 0x08, 0x4a},
    407
    408	{0x06, 0x00, 0x01},
    409	{0x06, 0x10, 0x02},
    410	{0x06, 0x64, 0x07},
    411	{0x06, 0x18, 0x08},
    412	{0x06, 0xfc, 0x09},
    413	{0x06, 0xfc, 0x0a},
    414	{0x06, 0xfc, 0x0b},
    415	{0x04, 0x00, 0x01},
    416	{0x06, 0x18, 0x0c},
    417	{0x06, 0xfc, 0x0d},
    418	{0x06, 0xfc, 0x0e},
    419	{0x06, 0xfc, 0x0f},
    420	{0x06, 0x11, 0x10},		/* contrast */
    421	{0x06, 0x00, 0x11},
    422	{0x06, 0xfe, 0x12},
    423	{0x06, 0x00, 0x13},
    424	{0x06, 0x00, 0x14},
    425	{0x06, 0x9d, 0x51},
    426	{0x06, 0x40, 0x52},
    427	{0x06, 0x7c, 0x53},
    428	{0x06, 0x40, 0x54},
    429	{0x06, 0x02, 0x57},
    430	{0x06, 0x03, 0x58},
    431	{0x06, 0x15, 0x59},
    432	{0x06, 0x05, 0x5a},
    433	{0x06, 0x03, 0x56},
    434	{0x06, 0x02, 0x3f},
    435	{0x06, 0x00, 0x40},
    436	{0x06, 0x39, 0x41},
    437	{0x06, 0x69, 0x42},
    438	{0x06, 0x87, 0x43},
    439	{0x06, 0x9e, 0x44},
    440	{0x06, 0xb1, 0x45},
    441	{0x06, 0xbf, 0x46},
    442	{0x06, 0xcc, 0x47},
    443	{0x06, 0xd5, 0x48},
    444	{0x06, 0xdd, 0x49},
    445	{0x06, 0xe3, 0x4a},
    446	{0x06, 0xe8, 0x4b},
    447	{0x06, 0xed, 0x4c},
    448	{0x06, 0xf2, 0x4d},
    449	{0x06, 0xf7, 0x4e},
    450	{0x06, 0xfc, 0x4f},
    451	{0x06, 0xff, 0x50},
    452
    453	{0x05, 0x01, 0xc0},
    454	{0x05, 0x10, 0xcb},
    455	{0x05, 0x40, 0xc1},
    456	{0x05, 0x04, 0xc2},
    457	{0x05, 0x00, 0xca},
    458	{0x05, 0x40, 0xc1},
    459	{0x05, 0x09, 0xc2},
    460	{0x05, 0x00, 0xca},
    461	{0x05, 0xc0, 0xc1},
    462	{0x05, 0x09, 0xc2},
    463	{0x05, 0x00, 0xca},
    464	{0x05, 0x40, 0xc1},
    465	{0x05, 0x59, 0xc2},
    466	{0x05, 0x00, 0xca},
    467	{0x04, 0x00, 0x01},
    468	{0x05, 0x80, 0xc1},
    469	{0x05, 0xec, 0xc2},
    470	{0x05, 0x0, 0xca},
    471
    472	{0x06, 0x02, 0x57},
    473	{0x06, 0x01, 0x58},
    474	{0x06, 0x15, 0x59},
    475	{0x06, 0x0a, 0x5a},
    476	{0x06, 0x01, 0x57},
    477	{0x06, 0x8a, 0x03},
    478	{0x06, 0x0a, 0x6c},
    479	{0x06, 0x30, 0x01},
    480	{0x06, 0x20, 0x02},
    481	{0x06, 0x00, 0x03},
    482
    483	{0x05, 0x8c, 0x25},
    484
    485	{0x06, 0x4d, 0x51},		/* maybe saturation (4d) */
    486	{0x06, 0x84, 0x53},		/* making green (84) */
    487	{0x06, 0x00, 0x57},		/* sharpness (1) */
    488	{0x06, 0x18, 0x08},
    489	{0x06, 0xfc, 0x09},
    490	{0x06, 0xfc, 0x0a},
    491	{0x06, 0xfc, 0x0b},
    492	{0x06, 0x18, 0x0c},		/* maybe hue (18) */
    493	{0x06, 0xfc, 0x0d},
    494	{0x06, 0xfc, 0x0e},
    495	{0x06, 0xfc, 0x0f},
    496	{0x06, 0x18, 0x10},		/* maybe contrast (18) */
    497
    498	{0x05, 0x01, 0x02},
    499
    500	{0x04, 0x00, 0x08},		/* compression */
    501	{0x04, 0x12, 0x09},
    502	{0x04, 0x21, 0x0a},
    503	{0x04, 0x10, 0x0b},
    504	{0x04, 0x21, 0x0c},
    505	{0x04, 0x1d, 0x00},		/* imagetype (1d) */
    506	{0x04, 0x41, 0x01},		/* hardware snapcontrol */
    507
    508	{0x04, 0x00, 0x04},
    509	{0x04, 0x00, 0x05},
    510	{0x04, 0x10, 0x06},
    511	{0x04, 0x10, 0x07},
    512	{0x04, 0x40, 0x06},
    513	{0x04, 0x40, 0x07},
    514	{0x04, 0x00, 0x04},
    515	{0x04, 0x00, 0x05},
    516
    517	{0x06, 0x1c, 0x17},
    518	{0x06, 0xe2, 0x19},
    519	{0x06, 0x1c, 0x1b},
    520	{0x06, 0xe2, 0x1d},
    521	{0x06, 0x5f, 0x1f},
    522	{0x06, 0x32, 0x20},
    523
    524	{0x05, initial_brightness >> 6, 0x00},
    525	{0x05, (initial_brightness << 2) & 0xff, 0x01},
    526	{0x05, 0x06, 0xc1},
    527	{0x05, 0x58, 0xc2},
    528	{0x05, 0x00, 0xca},
    529	{0x05, 0x00, 0x11},
    530	{}
    531};
    532
    533static int reg_write(struct gspca_dev *gspca_dev,
    534		     u16 req, u16 index, u16 value)
    535{
    536	int ret;
    537	struct usb_device *dev = gspca_dev->dev;
    538
    539	ret = usb_control_msg(dev,
    540			usb_sndctrlpipe(dev, 0),
    541			req,
    542			USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    543			value, index, NULL, 0, 500);
    544	gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",
    545		  req, index, value, ret);
    546	if (ret < 0)
    547		pr_err("reg write: error %d\n", ret);
    548	return ret;
    549}
    550
    551/* returns: negative is error, pos or zero is data */
    552static int reg_read(struct gspca_dev *gspca_dev,
    553			u16 req,	/* bRequest */
    554			u16 index)	/* wIndex */
    555{
    556	int ret;
    557
    558	ret = usb_control_msg(gspca_dev->dev,
    559			usb_rcvctrlpipe(gspca_dev->dev, 0),
    560			req,
    561			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
    562			0,			/* value */
    563			index,
    564			gspca_dev->usb_buf, 2,
    565			500);			/* timeout */
    566	if (ret < 0)
    567		return ret;
    568	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
    569}
    570
    571static int write_vector(struct gspca_dev *gspca_dev,
    572			const u8 data[][3])
    573{
    574	int ret, i = 0;
    575
    576	while (data[i][0] != 0) {
    577		ret = reg_write(gspca_dev, data[i][0], data[i][2],
    578								data[i][1]);
    579		if (ret < 0)
    580			return ret;
    581		i++;
    582	}
    583	return 0;
    584}
    585
    586/* this function is called at probe time */
    587static int sd_config(struct gspca_dev *gspca_dev,
    588			const struct usb_device_id *id)
    589{
    590	struct sd *sd = (struct sd *) gspca_dev;
    591	struct cam *cam;
    592
    593	cam = &gspca_dev->cam;
    594	cam->cam_mode = vga_mode;
    595	sd->subtype = id->driver_info;
    596	if (sd->subtype != IntelPCCameraPro)
    597		cam->nmodes = ARRAY_SIZE(vga_mode);
    598	else			/* no 640x480 for IntelPCCameraPro */
    599		cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
    600
    601	return 0;
    602}
    603
    604/* this function is called at probe and resume time */
    605static int sd_init(struct gspca_dev *gspca_dev)
    606{
    607	struct sd *sd = (struct sd *) gspca_dev;
    608
    609	if (write_vector(gspca_dev,
    610			 sd->subtype == Nxultra
    611				? spca505b_init_data
    612				: spca505_init_data))
    613		return -EIO;
    614	return 0;
    615}
    616
    617static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
    618{
    619	reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
    620	reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
    621}
    622
    623static int sd_start(struct gspca_dev *gspca_dev)
    624{
    625	struct sd *sd = (struct sd *) gspca_dev;
    626	int ret, mode;
    627	static u8 mode_tb[][3] = {
    628	/*	  r00   r06   r07	*/
    629		{0x00, 0x10, 0x10},	/* 640x480 */
    630		{0x01, 0x1a, 0x1a},	/* 352x288 */
    631		{0x02, 0x1c, 0x1d},	/* 320x240 */
    632		{0x04, 0x34, 0x34},	/* 176x144 */
    633		{0x05, 0x40, 0x40}	/* 160x120 */
    634	};
    635
    636	if (sd->subtype == Nxultra)
    637		write_vector(gspca_dev, spca505b_open_data_ccd);
    638	else
    639		write_vector(gspca_dev, spca505_open_data_ccd);
    640	ret = reg_read(gspca_dev, 0x06, 0x16);
    641
    642	if (ret < 0) {
    643		gspca_err(gspca_dev, "register read failed err: %d\n", ret);
    644		return ret;
    645	}
    646	if (ret != 0x0101) {
    647		pr_err("After vector read returns 0x%04x should be 0x0101\n",
    648		       ret);
    649	}
    650
    651	ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
    652	if (ret < 0)
    653		return ret;
    654	reg_write(gspca_dev, 0x05, 0xc2, 0x12);
    655
    656	/* necessary because without it we can see stream
    657	 * only once after loading module */
    658	/* stopping usb registers Tomasz change */
    659	reg_write(gspca_dev, 0x02, 0x00, 0x00);
    660
    661	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
    662	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
    663	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
    664	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
    665
    666	return reg_write(gspca_dev, SPCA50X_REG_USB,
    667			 SPCA50X_USB_CTRL,
    668			 SPCA50X_CUSB_ENABLE);
    669}
    670
    671static void sd_stopN(struct gspca_dev *gspca_dev)
    672{
    673	/* Disable ISO packet machine */
    674	reg_write(gspca_dev, 0x02, 0x00, 0x00);
    675}
    676
    677/* called on streamoff with alt 0 and on disconnect */
    678static void sd_stop0(struct gspca_dev *gspca_dev)
    679{
    680	if (!gspca_dev->present)
    681		return;
    682
    683	/* This maybe reset or power control */
    684	reg_write(gspca_dev, 0x03, 0x03, 0x20);
    685	reg_write(gspca_dev, 0x03, 0x01, 0x00);
    686	reg_write(gspca_dev, 0x03, 0x00, 0x01);
    687	reg_write(gspca_dev, 0x05, 0x10, 0x01);
    688	reg_write(gspca_dev, 0x05, 0x11, 0x0f);
    689}
    690
    691static void sd_pkt_scan(struct gspca_dev *gspca_dev,
    692			u8 *data,			/* isoc packet */
    693			int len)			/* iso packet length */
    694{
    695	switch (data[0]) {
    696	case 0:				/* start of frame */
    697		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
    698		data += SPCA50X_OFFSET_DATA;
    699		len -= SPCA50X_OFFSET_DATA;
    700		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
    701		break;
    702	case 0xff:			/* drop */
    703		break;
    704	default:
    705		data += 1;
    706		len -= 1;
    707		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
    708		break;
    709	}
    710}
    711
    712static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
    713{
    714	struct gspca_dev *gspca_dev =
    715		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
    716
    717	gspca_dev->usb_err = 0;
    718
    719	if (!gspca_dev->streaming)
    720		return 0;
    721
    722	switch (ctrl->id) {
    723	case V4L2_CID_BRIGHTNESS:
    724		setbrightness(gspca_dev, ctrl->val);
    725		break;
    726	}
    727	return gspca_dev->usb_err;
    728}
    729
    730static const struct v4l2_ctrl_ops sd_ctrl_ops = {
    731	.s_ctrl = sd_s_ctrl,
    732};
    733
    734static int sd_init_controls(struct gspca_dev *gspca_dev)
    735{
    736	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
    737
    738	gspca_dev->vdev.ctrl_handler = hdl;
    739	v4l2_ctrl_handler_init(hdl, 5);
    740	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
    741			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
    742
    743	if (hdl->error) {
    744		pr_err("Could not initialize controls\n");
    745		return hdl->error;
    746	}
    747	return 0;
    748}
    749
    750/* sub-driver description */
    751static const struct sd_desc sd_desc = {
    752	.name = MODULE_NAME,
    753	.config = sd_config,
    754	.init_controls = sd_init_controls,
    755	.init = sd_init,
    756	.start = sd_start,
    757	.stopN = sd_stopN,
    758	.stop0 = sd_stop0,
    759	.pkt_scan = sd_pkt_scan,
    760};
    761
    762/* -- module initialisation -- */
    763static const struct usb_device_id device_table[] = {
    764	{USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
    765	{USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
    766/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
    767	{}
    768};
    769MODULE_DEVICE_TABLE(usb, device_table);
    770
    771/* -- device connect -- */
    772static int sd_probe(struct usb_interface *intf,
    773			const struct usb_device_id *id)
    774{
    775	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
    776				THIS_MODULE);
    777}
    778
    779static struct usb_driver sd_driver = {
    780	.name = MODULE_NAME,
    781	.id_table = device_table,
    782	.probe = sd_probe,
    783	.disconnect = gspca_disconnect,
    784#ifdef CONFIG_PM
    785	.suspend = gspca_suspend,
    786	.resume = gspca_resume,
    787	.reset_resume = gspca_resume,
    788#endif
    789};
    790
    791module_usb_driver(sd_driver);