2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define MODULE_NAME "conex"
25 #define CONEX_CAM 1 /* special JPEG header */
28 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
30 MODULE_LICENSE("GPL");
32 /* specific webcam descriptor */
34 struct gspca_dev gspca_dev; /* !! must be the first item */
36 unsigned char brightness;
37 unsigned char contrast;
44 /* V4L2 controls supported by the driver */
45 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
46 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
47 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
48 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
49 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
50 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
52 static struct ctrl sd_ctrls[] = {
55 .id = V4L2_CID_BRIGHTNESS,
56 .type = V4L2_CTRL_TYPE_INTEGER,
61 #define BRIGHTNESS_DEF 0xd4
62 .default_value = BRIGHTNESS_DEF,
64 .set = sd_setbrightness,
65 .get = sd_getbrightness,
69 .id = V4L2_CID_CONTRAST,
70 .type = V4L2_CTRL_TYPE_INTEGER,
75 #define CONTRAST_DEF 0x0c
76 .default_value = CONTRAST_DEF,
78 .set = sd_setcontrast,
79 .get = sd_getcontrast,
83 .id = V4L2_CID_SATURATION,
84 .type = V4L2_CTRL_TYPE_INTEGER,
90 .default_value = COLOR_DEF,
97 static const struct v4l2_pix_format vga_mode[] = {
98 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100 .sizeimage = 176 * 144 * 3 / 8 + 590,
101 .colorspace = V4L2_COLORSPACE_JPEG,
103 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
105 .sizeimage = 320 * 240 * 3 / 8 + 590,
106 .colorspace = V4L2_COLORSPACE_JPEG,
108 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
110 .sizeimage = 352 * 288 * 3 / 8 + 590,
111 .colorspace = V4L2_COLORSPACE_JPEG,
113 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
115 .sizeimage = 640 * 480 * 3 / 8 + 590,
116 .colorspace = V4L2_COLORSPACE_JPEG,
120 /* the read bytes are found in gspca_dev->usb_buf */
121 static void reg_r(struct gspca_dev *gspca_dev,
125 struct usb_device *dev = gspca_dev->dev;
128 if (len > USB_BUF_SZ) {
129 err("reg_r: buffer overflow");
134 usb_rcvctrlpipe(dev, 0),
136 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
138 index, gspca_dev->usb_buf, len,
140 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
141 index, gspca_dev->usb_buf[0]);
144 /* the bytes to write are in gspca_dev->usb_buf */
145 static void reg_w_val(struct gspca_dev *gspca_dev,
149 struct usb_device *dev = gspca_dev->dev;
151 gspca_dev->usb_buf[0] = val;
153 usb_sndctrlpipe(dev, 0),
155 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
157 index, gspca_dev->usb_buf, 1, 500);
160 static void reg_w(struct gspca_dev *gspca_dev,
165 struct usb_device *dev = gspca_dev->dev;
168 if (len > USB_BUF_SZ) {
169 err("reg_w: buffer overflow");
172 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
174 memcpy(gspca_dev->usb_buf, buffer, len);
176 usb_sndctrlpipe(dev, 0),
178 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
180 index, gspca_dev->usb_buf, len, 500);
183 static const __u8 cx_sensor_init[][4] = {
184 {0x88, 0x11, 0x01, 0x01},
185 {0x88, 0x12, 0x70, 0x01},
186 {0x88, 0x0f, 0x00, 0x01},
187 {0x88, 0x05, 0x01, 0x01},
191 static const __u8 cx11646_fw1[][3] = {
258 static void cx11646_fw(struct gspca_dev*gspca_dev)
262 reg_w_val(gspca_dev, 0x006a, 0x02);
263 while (cx11646_fw1[i][1]) {
264 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
267 reg_w_val(gspca_dev, 0x006a, 0x00);
270 static const __u8 cxsensor[] = {
271 0x88, 0x12, 0x70, 0x01,
272 0x88, 0x0d, 0x02, 0x01,
273 0x88, 0x0f, 0x00, 0x01,
274 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
275 0x88, 0x02, 0x10, 0x01,
276 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
277 0x88, 0x0B, 0x00, 0x01,
278 0x88, 0x0A, 0x0A, 0x01,
279 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
280 0x88, 0x05, 0x01, 0x01,
281 0xA1, 0x18, 0x00, 0x01,
285 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
286 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
287 static const __u8 reg10[] = { 0xb1, 0xb1 };
288 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
289 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
290 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
291 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
292 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
293 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
294 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
296 static void cx_sensor(struct gspca_dev*gspca_dev)
300 const __u8 *ptsensor = cxsensor;
302 reg_w(gspca_dev, 0x0020, reg20, 8);
303 reg_w(gspca_dev, 0x0028, reg28, 8);
304 reg_w(gspca_dev, 0x0010, reg10, 8);
305 reg_w_val(gspca_dev, 0x0092, 0x03);
307 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
309 reg_w(gspca_dev, 0x0071, reg71a, 4);
312 reg_w(gspca_dev, 0x0071, reg71b, 4);
316 reg_w(gspca_dev, 0x0071, reg71c, 4);
319 reg_w(gspca_dev, 0x0071, reg71d, 4);
322 reg_w(gspca_dev, 0x007b, reg7b, 6);
323 reg_w_val(gspca_dev, 0x00f8, 0x00);
324 reg_w(gspca_dev, 0x0010, reg10, 8);
325 reg_w_val(gspca_dev, 0x0098, 0x41);
326 for (i = 0; i < 11; i++) {
327 if (i == 3 || i == 5 || i == 8)
331 reg_w(gspca_dev, 0x00e5, ptsensor, length);
333 reg_r(gspca_dev, 0x00e8, 1);
335 reg_r(gspca_dev, 0x00e8, length);
338 reg_r(gspca_dev, 0x00e7, 8);
341 static const __u8 cx_inits_176[] = {
342 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
343 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
344 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
345 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
346 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
347 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
348 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
350 static const __u8 cx_inits_320[] = {
351 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
352 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
353 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
354 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
355 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
356 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
357 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
359 static const __u8 cx_inits_352[] = {
360 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
361 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
362 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
363 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
364 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
365 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
366 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
368 static const __u8 cx_inits_640[] = {
369 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
370 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
371 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
372 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
373 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
374 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
375 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
378 static void cx11646_initsize(struct gspca_dev *gspca_dev)
381 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
382 static const __u8 reg17[] =
383 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
385 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
387 cxinit = cx_inits_640;
390 cxinit = cx_inits_352;
394 cxinit = cx_inits_320;
397 cxinit = cx_inits_176;
400 reg_w_val(gspca_dev, 0x009a, 0x01);
401 reg_w_val(gspca_dev, 0x0010, 0x10);
402 reg_w(gspca_dev, 0x0012, reg12, 5);
403 reg_w(gspca_dev, 0x0017, reg17, 8);
404 reg_w_val(gspca_dev, 0x00c0, 0x00);
405 reg_w_val(gspca_dev, 0x00c1, 0x04);
406 reg_w_val(gspca_dev, 0x00c2, 0x04);
408 reg_w(gspca_dev, 0x0061, cxinit, 8);
410 reg_w(gspca_dev, 0x00ca, cxinit, 8);
412 reg_w(gspca_dev, 0x00d2, cxinit, 8);
414 reg_w(gspca_dev, 0x00da, cxinit, 6);
416 reg_w(gspca_dev, 0x0041, cxinit, 8);
418 reg_w(gspca_dev, 0x0049, cxinit, 8);
420 reg_w(gspca_dev, 0x0051, cxinit, 2);
422 reg_r(gspca_dev, 0x0010, 1);
425 static const __u8 cx_jpeg_init[][8] = {
426 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
427 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
428 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
429 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
430 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
431 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
432 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
433 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
434 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
435 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
436 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
437 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
438 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
439 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
440 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
441 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
442 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
443 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
444 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
445 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
446 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
447 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
448 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
449 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
450 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
451 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
452 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
453 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
454 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
455 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
456 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
457 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
458 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
459 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
460 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
461 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
462 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
463 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
464 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
465 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
466 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
467 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
468 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
469 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
470 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
471 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
472 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
473 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
474 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
475 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
476 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
477 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
478 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
479 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
480 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
481 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
482 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
483 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
484 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
485 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
486 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
487 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
488 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
489 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
490 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
491 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
492 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
493 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
494 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
495 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
496 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
497 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
498 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
499 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
500 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
501 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
502 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
503 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
504 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
508 static const __u8 cxjpeg_640[][8] = {
509 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
510 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
511 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
512 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
513 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
514 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
515 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
516 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
517 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
518 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
519 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
520 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
521 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
522 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
523 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
524 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
525 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
526 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
527 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
528 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
529 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
530 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
531 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
532 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
533 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
534 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
535 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
537 static const __u8 cxjpeg_352[][8] = {
538 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
539 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
540 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
541 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
542 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
543 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
544 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
545 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
546 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
547 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
548 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
549 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
550 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
551 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
552 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
553 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
554 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
555 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
556 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
557 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
558 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
559 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
560 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
561 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
562 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
563 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
564 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
566 static const __u8 cxjpeg_320[][8] = {
567 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
568 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
569 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
570 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
571 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
572 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
573 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
574 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
575 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
576 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
577 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
578 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
579 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
580 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
581 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
582 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
583 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
584 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
585 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
586 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
587 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
588 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
589 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
590 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
591 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
592 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
593 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
595 static const __u8 cxjpeg_176[][8] = {
596 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
597 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
598 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
599 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
600 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
601 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
602 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
603 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
604 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
605 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
606 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
607 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
608 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
609 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
610 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
611 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
612 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
613 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
614 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
615 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
616 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
617 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
618 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
619 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
620 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
621 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
622 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
624 /* 640 take with the zcx30x part */
625 static const __u8 cxjpeg_qtable[][8] = {
626 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
627 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
628 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
629 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
630 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
631 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
632 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
633 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
634 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
635 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
636 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
637 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
638 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
639 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
640 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
647 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
652 reg_w_val(gspca_dev, 0x00c0, 0x01);
653 reg_w_val(gspca_dev, 0x00c3, 0x00);
654 reg_w_val(gspca_dev, 0x00c0, 0x00);
655 reg_r(gspca_dev, 0x0001, 1);
657 for (i = 0; i < 79; i++) {
660 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
662 reg_r(gspca_dev, 0x0002, 1);
663 reg_w_val(gspca_dev, 0x0055, 0x14);
666 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
667 static const __u8 regE5_8[] =
668 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
669 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
670 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
671 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
672 static const __u8 reg51[] = { 0x77, 0x03 };
675 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
682 reg_w_val(gspca_dev, 0x00c0, 0x01);
683 reg_w_val(gspca_dev, 0x00c3, 0x00);
684 reg_w_val(gspca_dev, 0x00c0, 0x00);
685 reg_r(gspca_dev, 0x0001, 1);
687 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
689 for (i = 0; i < 27; i++) {
692 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
697 for (i = 0; i < 27; i++) {
700 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
706 for (i = 0; i < 27; i++) {
709 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
714 for (i = 0; i < 27; i++) {
717 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
723 reg_r(gspca_dev, 0x0002, 1);
724 reg_w_val(gspca_dev, 0x0055, Reg55);
725 reg_r(gspca_dev, 0x0002, 1);
726 reg_w(gspca_dev, 0x0010, reg10, 2);
727 reg_w_val(gspca_dev, 0x0054, 0x02);
728 reg_w_val(gspca_dev, 0x0054, 0x01);
729 reg_w_val(gspca_dev, 0x0000, 0x94);
730 reg_w_val(gspca_dev, 0x0053, 0xc0);
731 reg_w_val(gspca_dev, 0x00fc, 0xe1);
732 reg_w_val(gspca_dev, 0x0000, 0x00);
733 /* wait for completion */
736 reg_r(gspca_dev, 0x0002, 1);
737 /* 0x07 until 0x00 */
738 if (gspca_dev->usb_buf[0] == 0x00)
740 reg_w_val(gspca_dev, 0x0053, 0x00);
743 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
744 /* send the qtable now */
745 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
747 for (i = 0; i < 18; i++) {
750 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
753 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
754 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
755 reg_w_val(gspca_dev, 0x0054, 0x02);
756 reg_w_val(gspca_dev, 0x0054, 0x01);
757 reg_w_val(gspca_dev, 0x0000, 0x94);
758 reg_w_val(gspca_dev, 0x0053, 0xc0);
760 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
761 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
762 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
763 reg_w(gspca_dev, 0x0012, reg12, 5);
764 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
765 reg_r(gspca_dev, 0x00e8, 8);
766 reg_w(gspca_dev, 0x00e5, regE5a, 4);
767 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
768 reg_w_val(gspca_dev, 0x009a, 0x01);
769 reg_w(gspca_dev, 0x00e5, regE5b, 4);
770 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
771 reg_w(gspca_dev, 0x00e5, regE5c, 4);
772 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
774 reg_w(gspca_dev, 0x0051, reg51, 2);
775 reg_w(gspca_dev, 0x0010, reg10, 2);
776 reg_w_val(gspca_dev, 0x0070, reg70);
779 static void cx11646_init1(struct gspca_dev *gspca_dev)
783 reg_w_val(gspca_dev, 0x0010, 0x00);
784 reg_w_val(gspca_dev, 0x0053, 0x00);
785 reg_w_val(gspca_dev, 0x0052, 0x00);
786 reg_w_val(gspca_dev, 0x009b, 0x2f);
787 reg_w_val(gspca_dev, 0x009c, 0x10);
788 reg_r(gspca_dev, 0x0098, 1);
789 reg_w_val(gspca_dev, 0x0098, 0x40);
790 reg_r(gspca_dev, 0x0099, 1);
791 reg_w_val(gspca_dev, 0x0099, 0x07);
792 reg_w_val(gspca_dev, 0x0039, 0x40);
793 reg_w_val(gspca_dev, 0x003c, 0xff);
794 reg_w_val(gspca_dev, 0x003f, 0x1f);
795 reg_w_val(gspca_dev, 0x003d, 0x40);
796 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
797 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
799 while (cx_sensor_init[i][0]) {
800 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
801 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
803 reg_w_val(gspca_dev, 0x00ed, 0x01);
804 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
808 reg_w_val(gspca_dev, 0x00c3, 0x00);
811 /* this function is called at probe time */
812 static int sd_config(struct gspca_dev *gspca_dev,
813 const struct usb_device_id *id)
815 struct sd *sd = (struct sd *) gspca_dev;
818 cam = &gspca_dev->cam;
819 cam->cam_mode = vga_mode;
820 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
822 sd->brightness = BRIGHTNESS_DEF;
823 sd->contrast = CONTRAST_DEF;
824 sd->colors = COLOR_DEF;
829 /* this function is called at probe and resume time */
830 static int sd_init(struct gspca_dev *gspca_dev)
832 cx11646_init1(gspca_dev);
833 cx11646_initsize(gspca_dev);
834 cx11646_fw(gspca_dev);
835 cx_sensor(gspca_dev);
836 cx11646_jpegInit(gspca_dev);
840 static int sd_start(struct gspca_dev *gspca_dev)
842 struct sd *sd = (struct sd *) gspca_dev;
844 /* create the JPEG header */
845 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
846 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
847 0x22); /* JPEG 411 */
848 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
850 cx11646_initsize(gspca_dev);
851 cx11646_fw(gspca_dev);
852 cx_sensor(gspca_dev);
853 cx11646_jpeg(gspca_dev);
857 /* called on streamoff with alt 0 and on disconnect */
858 static void sd_stop0(struct gspca_dev *gspca_dev)
860 struct sd *sd = (struct sd *) gspca_dev;
865 if (!gspca_dev->present)
867 reg_w_val(gspca_dev, 0x0000, 0x00);
868 reg_r(gspca_dev, 0x0002, 1);
869 reg_w_val(gspca_dev, 0x0053, 0x00);
872 /* reg_r(gspca_dev, 0x0002, 1);*/
873 reg_r(gspca_dev, 0x0053, 1);
874 if (gspca_dev->usb_buf[0] == 0)
877 reg_w_val(gspca_dev, 0x0000, 0x00);
878 reg_r(gspca_dev, 0x0002, 1);
880 reg_w_val(gspca_dev, 0x0010, 0x00);
881 reg_r(gspca_dev, 0x0033, 1);
882 reg_w_val(gspca_dev, 0x00fc, 0xe0);
885 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
886 struct gspca_frame *frame, /* target */
887 __u8 *data, /* isoc packet */
888 int len) /* iso packet length */
890 struct sd *sd = (struct sd *) gspca_dev;
892 if (data[0] == 0xff && data[1] == 0xd8) {
895 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
898 /* put the JPEG header in the new frame */
899 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
900 sd->jpeg_hdr, JPEG_HDR_SZ);
904 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
907 static void setbrightness(struct gspca_dev*gspca_dev)
909 struct sd *sd = (struct sd *) gspca_dev;
910 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
915 bright = sd->brightness;
916 regE5cbx[2] = bright;
917 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
918 reg_r(gspca_dev, 0x00e8, 8);
919 reg_w(gspca_dev, 0x00e5, regE5c, 4);
920 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
925 reg_w(gspca_dev, 0x0051, reg51c, 2);
926 reg_w(gspca_dev, 0x0010, reg10, 2);
927 reg_w_val(gspca_dev, 0x0070, reg70);
930 static void setcontrast(struct gspca_dev*gspca_dev)
932 struct sd *sd = (struct sd *) gspca_dev;
933 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
934 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
937 regE5acx[2] = sd->contrast;
938 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
939 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
941 reg51c[1] = sd->colors;
942 reg_w(gspca_dev, 0x0051, reg51c, 2);
943 reg_w(gspca_dev, 0x0010, reg10, 2);
944 reg_w_val(gspca_dev, 0x0070, reg70);
947 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
949 struct sd *sd = (struct sd *) gspca_dev;
951 sd->brightness = val;
952 if (gspca_dev->streaming)
953 setbrightness(gspca_dev);
957 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
959 struct sd *sd = (struct sd *) gspca_dev;
961 *val = sd->brightness;
965 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
967 struct sd *sd = (struct sd *) gspca_dev;
970 if (gspca_dev->streaming)
971 setcontrast(gspca_dev);
975 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
977 struct sd *sd = (struct sd *) gspca_dev;
983 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
985 struct sd *sd = (struct sd *) gspca_dev;
988 if (gspca_dev->streaming) {
989 setbrightness(gspca_dev);
990 setcontrast(gspca_dev);
995 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
997 struct sd *sd = (struct sd *) gspca_dev;
1003 /* sub-driver description */
1004 static struct sd_desc sd_desc = {
1005 .name = MODULE_NAME,
1007 .nctrls = ARRAY_SIZE(sd_ctrls),
1008 .config = sd_config,
1012 .pkt_scan = sd_pkt_scan,
1015 /* -- module initialisation -- */
1016 static __devinitdata struct usb_device_id device_table[] = {
1017 {USB_DEVICE(0x0572, 0x0041)},
1020 MODULE_DEVICE_TABLE(usb, device_table);
1022 /* -- device connect -- */
1023 static int sd_probe(struct usb_interface *intf,
1024 const struct usb_device_id *id)
1026 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1030 static struct usb_driver sd_driver = {
1031 .name = MODULE_NAME,
1032 .id_table = device_table,
1034 .disconnect = gspca_disconnect,
1036 .suspend = gspca_suspend,
1037 .resume = gspca_resume,
1041 /* -- module insert / remove -- */
1042 static int __init sd_mod_init(void)
1045 ret = usb_register(&sd_driver);
1048 PDEBUG(D_PROBE, "registered");
1051 static void __exit sd_mod_exit(void)
1053 usb_deregister(&sd_driver);
1054 PDEBUG(D_PROBE, "deregistered");
1057 module_init(sd_mod_init);
1058 module_exit(sd_mod_exit);