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;
43 /* V4L2 controls supported by the driver */
44 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
45 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
46 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
47 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
48 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
49 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
51 static struct ctrl sd_ctrls[] = {
54 .id = V4L2_CID_BRIGHTNESS,
55 .type = V4L2_CTRL_TYPE_INTEGER,
60 #define BRIGHTNESS_DEF 0xd4
61 .default_value = BRIGHTNESS_DEF,
63 .set = sd_setbrightness,
64 .get = sd_getbrightness,
68 .id = V4L2_CID_CONTRAST,
69 .type = V4L2_CTRL_TYPE_INTEGER,
74 #define CONTRAST_DEF 0x0c
75 .default_value = CONTRAST_DEF,
77 .set = sd_setcontrast,
78 .get = sd_getcontrast,
82 .id = V4L2_CID_SATURATION,
83 .type = V4L2_CTRL_TYPE_INTEGER,
89 .default_value = COLOR_DEF,
96 static struct v4l2_pix_format vga_mode[] = {
97 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
99 .sizeimage = 176 * 144 * 3 / 8 + 590,
100 .colorspace = V4L2_COLORSPACE_JPEG,
102 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
104 .sizeimage = 320 * 240 * 3 / 8 + 590,
105 .colorspace = V4L2_COLORSPACE_JPEG,
107 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
109 .sizeimage = 352 * 288 * 3 / 8 + 590,
110 .colorspace = V4L2_COLORSPACE_JPEG,
112 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
114 .sizeimage = 640 * 480 * 3 / 8 + 590,
115 .colorspace = V4L2_COLORSPACE_JPEG,
119 /* the read bytes are found in gspca_dev->usb_buf */
120 static void reg_r(struct gspca_dev *gspca_dev,
124 struct usb_device *dev = gspca_dev->dev;
127 if (len > USB_BUF_SZ) {
128 err("reg_r: buffer overflow");
133 usb_rcvctrlpipe(dev, 0),
135 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
137 index, gspca_dev->usb_buf, len,
139 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
140 index, gspca_dev->usb_buf[0]);
143 /* the bytes to write are in gspca_dev->usb_buf */
144 static void reg_w_val(struct gspca_dev *gspca_dev,
148 struct usb_device *dev = gspca_dev->dev;
150 gspca_dev->usb_buf[0] = val;
152 usb_sndctrlpipe(dev, 0),
154 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
156 index, gspca_dev->usb_buf, 1, 500);
159 static void reg_w(struct gspca_dev *gspca_dev,
164 struct usb_device *dev = gspca_dev->dev;
167 if (len > USB_BUF_SZ) {
168 err("reg_w: buffer overflow");
171 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
173 memcpy(gspca_dev->usb_buf, buffer, len);
175 usb_sndctrlpipe(dev, 0),
177 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
179 index, gspca_dev->usb_buf, len, 500);
182 static const __u8 cx_sensor_init[][4] = {
183 {0x88, 0x11, 0x01, 0x01},
184 {0x88, 0x12, 0x70, 0x01},
185 {0x88, 0x0f, 0x00, 0x01},
186 {0x88, 0x05, 0x01, 0x01},
190 static const __u8 cx11646_fw1[][3] = {
257 static void cx11646_fw(struct gspca_dev*gspca_dev)
261 reg_w_val(gspca_dev, 0x006a, 0x02);
262 while (cx11646_fw1[i][1]) {
263 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
266 reg_w_val(gspca_dev, 0x006a, 0x00);
269 static const __u8 cxsensor[] = {
270 0x88, 0x12, 0x70, 0x01,
271 0x88, 0x0d, 0x02, 0x01,
272 0x88, 0x0f, 0x00, 0x01,
273 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
274 0x88, 0x02, 0x10, 0x01,
275 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
276 0x88, 0x0B, 0x00, 0x01,
277 0x88, 0x0A, 0x0A, 0x01,
278 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
279 0x88, 0x05, 0x01, 0x01,
280 0xA1, 0x18, 0x00, 0x01,
284 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
285 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
286 static const __u8 reg10[] = { 0xb1, 0xb1 };
287 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
288 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
289 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
290 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
291 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
292 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
293 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
295 static void cx_sensor(struct gspca_dev*gspca_dev)
299 const __u8 *ptsensor = cxsensor;
301 reg_w(gspca_dev, 0x0020, reg20, 8);
302 reg_w(gspca_dev, 0x0028, reg28, 8);
303 reg_w(gspca_dev, 0x0010, reg10, 8);
304 reg_w_val(gspca_dev, 0x0092, 0x03);
306 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
308 reg_w(gspca_dev, 0x0071, reg71a, 4);
311 reg_w(gspca_dev, 0x0071, reg71b, 4);
315 reg_w(gspca_dev, 0x0071, reg71c, 4);
318 reg_w(gspca_dev, 0x0071, reg71d, 4);
321 reg_w(gspca_dev, 0x007b, reg7b, 6);
322 reg_w_val(gspca_dev, 0x00f8, 0x00);
323 reg_w(gspca_dev, 0x0010, reg10, 8);
324 reg_w_val(gspca_dev, 0x0098, 0x41);
325 for (i = 0; i < 11; i++) {
326 if (i == 3 || i == 5 || i == 8)
330 reg_w(gspca_dev, 0x00e5, ptsensor, length);
332 reg_r(gspca_dev, 0x00e8, 1);
334 reg_r(gspca_dev, 0x00e8, length);
337 reg_r(gspca_dev, 0x00e7, 8);
340 static const __u8 cx_inits_176[] = {
341 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
342 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
343 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
344 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
345 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
346 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
347 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
349 static const __u8 cx_inits_320[] = {
350 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
351 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
352 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
353 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
354 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
355 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
356 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
358 static const __u8 cx_inits_352[] = {
359 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
360 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
361 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
362 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
363 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
364 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
365 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
367 static const __u8 cx_inits_640[] = {
368 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
369 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
370 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
371 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
372 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
373 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
374 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
377 static void cx11646_initsize(struct gspca_dev *gspca_dev)
380 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
381 static const __u8 reg17[] =
382 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
384 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
386 cxinit = cx_inits_640;
389 cxinit = cx_inits_352;
393 cxinit = cx_inits_320;
396 cxinit = cx_inits_176;
399 reg_w_val(gspca_dev, 0x009a, 0x01);
400 reg_w_val(gspca_dev, 0x0010, 0x10);
401 reg_w(gspca_dev, 0x0012, reg12, 5);
402 reg_w(gspca_dev, 0x0017, reg17, 8);
403 reg_w_val(gspca_dev, 0x00c0, 0x00);
404 reg_w_val(gspca_dev, 0x00c1, 0x04);
405 reg_w_val(gspca_dev, 0x00c2, 0x04);
407 reg_w(gspca_dev, 0x0061, cxinit, 8);
409 reg_w(gspca_dev, 0x00ca, cxinit, 8);
411 reg_w(gspca_dev, 0x00d2, cxinit, 8);
413 reg_w(gspca_dev, 0x00da, cxinit, 6);
415 reg_w(gspca_dev, 0x0041, cxinit, 8);
417 reg_w(gspca_dev, 0x0049, cxinit, 8);
419 reg_w(gspca_dev, 0x0051, cxinit, 2);
421 reg_r(gspca_dev, 0x0010, 1);
424 static const __u8 cx_jpeg_init[][8] = {
425 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
426 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
427 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
428 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
429 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
430 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
431 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
432 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
433 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
434 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
435 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
436 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
437 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
438 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
439 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
440 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
441 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
442 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
443 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
444 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
445 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
446 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
447 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
448 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
449 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
450 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
451 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
452 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
453 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
454 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
455 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
456 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
457 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
458 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
459 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
460 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
461 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
462 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
463 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
464 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
465 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
466 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
467 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
468 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
469 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
470 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
471 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
472 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
473 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
474 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
475 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
476 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
477 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
478 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
479 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
480 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
481 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
482 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
483 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
484 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
485 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
486 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
487 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
488 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
489 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
490 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
491 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
492 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
493 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
494 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
495 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
496 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
497 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
498 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
499 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
500 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
501 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
502 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
503 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
507 static const __u8 cxjpeg_640[][8] = {
508 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
509 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
510 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
511 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
512 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
513 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
514 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
515 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
516 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
517 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
518 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
519 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
520 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
521 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
522 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
523 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
524 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
525 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
526 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
527 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
528 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
529 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
530 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
531 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
532 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
533 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
534 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
536 static const __u8 cxjpeg_352[][8] = {
537 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
538 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
539 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
540 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
541 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
542 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
543 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
544 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
545 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
546 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
547 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
548 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
549 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
550 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
551 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
552 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
553 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
554 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
555 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
556 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
557 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
558 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
559 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
560 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
561 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
562 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
563 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
565 static const __u8 cxjpeg_320[][8] = {
566 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
567 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
568 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
569 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
570 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
571 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
572 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
573 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
574 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
575 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
576 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
577 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
578 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
579 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
580 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
581 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
582 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
583 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
584 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
585 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
586 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
587 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
588 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
589 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
590 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
591 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
592 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
594 static const __u8 cxjpeg_176[][8] = {
595 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
596 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
597 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
598 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
599 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
600 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
601 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
602 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
603 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
604 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
605 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
606 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
607 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
608 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
609 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
610 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
611 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
612 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
613 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
614 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
615 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
616 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
617 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
618 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
619 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
620 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
621 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
623 /* 640 take with the zcx30x part */
624 static const __u8 cxjpeg_qtable[][8] = {
625 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
626 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
627 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
628 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
629 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
630 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
631 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
632 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
633 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
634 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
635 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
636 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 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 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
646 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
651 reg_w_val(gspca_dev, 0x00c0, 0x01);
652 reg_w_val(gspca_dev, 0x00c3, 0x00);
653 reg_w_val(gspca_dev, 0x00c0, 0x00);
654 reg_r(gspca_dev, 0x0001, 1);
656 for (i = 0; i < 79; i++) {
659 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
661 reg_r(gspca_dev, 0x0002, 1);
662 reg_w_val(gspca_dev, 0x0055, 0x14);
665 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
666 static const __u8 regE5_8[] =
667 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
668 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
669 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
670 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
671 static const __u8 reg51[] = { 0x77, 0x03 };
674 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
681 reg_w_val(gspca_dev, 0x00c0, 0x01);
682 reg_w_val(gspca_dev, 0x00c3, 0x00);
683 reg_w_val(gspca_dev, 0x00c0, 0x00);
684 reg_r(gspca_dev, 0x0001, 1);
686 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
688 for (i = 0; i < 27; i++) {
691 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
696 for (i = 0; i < 27; i++) {
699 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
705 for (i = 0; i < 27; i++) {
708 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
713 for (i = 0; i < 27; i++) {
716 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
722 reg_r(gspca_dev, 0x0002, 1);
723 reg_w_val(gspca_dev, 0x0055, Reg55);
724 reg_r(gspca_dev, 0x0002, 1);
725 reg_w(gspca_dev, 0x0010, reg10, 2);
726 reg_w_val(gspca_dev, 0x0054, 0x02);
727 reg_w_val(gspca_dev, 0x0054, 0x01);
728 reg_w_val(gspca_dev, 0x0000, 0x94);
729 reg_w_val(gspca_dev, 0x0053, 0xc0);
730 reg_w_val(gspca_dev, 0x00fc, 0xe1);
731 reg_w_val(gspca_dev, 0x0000, 0x00);
732 /* wait for completion */
735 reg_r(gspca_dev, 0x0002, 1);
736 /* 0x07 until 0x00 */
737 if (gspca_dev->usb_buf[0] == 0x00)
739 reg_w_val(gspca_dev, 0x0053, 0x00);
742 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
743 /* send the qtable now */
744 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
746 for (i = 0; i < 18; i++) {
749 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
752 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
753 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
754 reg_w_val(gspca_dev, 0x0054, 0x02);
755 reg_w_val(gspca_dev, 0x0054, 0x01);
756 reg_w_val(gspca_dev, 0x0000, 0x94);
757 reg_w_val(gspca_dev, 0x0053, 0xc0);
759 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
760 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
761 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
762 reg_w(gspca_dev, 0x0012, reg12, 5);
763 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
764 reg_r(gspca_dev, 0x00e8, 8);
765 reg_w(gspca_dev, 0x00e5, regE5a, 4);
766 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
767 reg_w_val(gspca_dev, 0x009a, 0x01);
768 reg_w(gspca_dev, 0x00e5, regE5b, 4);
769 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
770 reg_w(gspca_dev, 0x00e5, regE5c, 4);
771 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
773 reg_w(gspca_dev, 0x0051, reg51, 2);
774 reg_w(gspca_dev, 0x0010, reg10, 2);
775 reg_w_val(gspca_dev, 0x0070, reg70);
778 static void cx11646_init1(struct gspca_dev *gspca_dev)
782 reg_w_val(gspca_dev, 0x0010, 0x00);
783 reg_w_val(gspca_dev, 0x0053, 0x00);
784 reg_w_val(gspca_dev, 0x0052, 0x00);
785 reg_w_val(gspca_dev, 0x009b, 0x2f);
786 reg_w_val(gspca_dev, 0x009c, 0x10);
787 reg_r(gspca_dev, 0x0098, 1);
788 reg_w_val(gspca_dev, 0x0098, 0x40);
789 reg_r(gspca_dev, 0x0099, 1);
790 reg_w_val(gspca_dev, 0x0099, 0x07);
791 reg_w_val(gspca_dev, 0x0039, 0x40);
792 reg_w_val(gspca_dev, 0x003c, 0xff);
793 reg_w_val(gspca_dev, 0x003f, 0x1f);
794 reg_w_val(gspca_dev, 0x003d, 0x40);
795 /* reg_w_val(gspca_dev, 0x003d, 0x60); */
796 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
798 while (cx_sensor_init[i][0]) {
799 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
800 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
802 reg_w_val(gspca_dev, 0x00ed, 0x01);
803 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
807 reg_w_val(gspca_dev, 0x00c3, 0x00);
810 /* this function is called at probe time */
811 static int sd_config(struct gspca_dev *gspca_dev,
812 const struct usb_device_id *id)
814 struct sd *sd = (struct sd *) gspca_dev;
817 cam = &gspca_dev->cam;
819 cam->cam_mode = vga_mode;
820 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
822 sd->qindex = 0; /* set the quantization */
823 sd->brightness = BRIGHTNESS_DEF;
824 sd->contrast = CONTRAST_DEF;
825 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 cx11646_initsize(gspca_dev);
843 cx11646_fw(gspca_dev);
844 cx_sensor(gspca_dev);
845 cx11646_jpeg(gspca_dev);
849 static void sd_stop0(struct gspca_dev *gspca_dev)
853 reg_w_val(gspca_dev, 0x0000, 0x00);
854 reg_r(gspca_dev, 0x0002, 1);
855 reg_w_val(gspca_dev, 0x0053, 0x00);
858 /* reg_r(gspca_dev, 0x0002, 1);*/
859 reg_r(gspca_dev, 0x0053, 1);
860 if (gspca_dev->usb_buf[0] == 0)
863 reg_w_val(gspca_dev, 0x0000, 0x00);
864 reg_r(gspca_dev, 0x0002, 1);
866 reg_w_val(gspca_dev, 0x0010, 0x00);
867 reg_r(gspca_dev, 0x0033, 1);
868 reg_w_val(gspca_dev, 0x00fc, 0xe0);
871 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
872 struct gspca_frame *frame, /* target */
873 __u8 *data, /* isoc packet */
874 int len) /* iso packet length */
876 if (data[0] == 0xff && data[1] == 0xd8) {
879 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
882 /* put the JPEG header in the new frame */
883 jpeg_put_header(gspca_dev, frame,
884 ((struct sd *) gspca_dev)->qindex,
889 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
892 static void setbrightness(struct gspca_dev*gspca_dev)
894 struct sd *sd = (struct sd *) gspca_dev;
895 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
900 bright = sd->brightness;
901 regE5cbx[2] = bright;
902 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
903 reg_r(gspca_dev, 0x00e8, 8);
904 reg_w(gspca_dev, 0x00e5, regE5c, 4);
905 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
910 reg_w(gspca_dev, 0x0051, reg51c, 2);
911 reg_w(gspca_dev, 0x0010, reg10, 2);
912 reg_w_val(gspca_dev, 0x0070, reg70);
915 static void setcontrast(struct gspca_dev*gspca_dev)
917 struct sd *sd = (struct sd *) gspca_dev;
918 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
919 /* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
922 regE5acx[2] = sd->contrast;
923 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
924 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
926 reg51c[1] = sd->colors;
927 reg_w(gspca_dev, 0x0051, reg51c, 2);
928 reg_w(gspca_dev, 0x0010, reg10, 2);
929 reg_w_val(gspca_dev, 0x0070, reg70);
932 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
934 struct sd *sd = (struct sd *) gspca_dev;
936 sd->brightness = val;
937 if (gspca_dev->streaming)
938 setbrightness(gspca_dev);
942 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
944 struct sd *sd = (struct sd *) gspca_dev;
946 *val = sd->brightness;
950 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
952 struct sd *sd = (struct sd *) gspca_dev;
955 if (gspca_dev->streaming)
956 setcontrast(gspca_dev);
960 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
962 struct sd *sd = (struct sd *) gspca_dev;
968 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
970 struct sd *sd = (struct sd *) gspca_dev;
973 if (gspca_dev->streaming) {
974 setbrightness(gspca_dev);
975 setcontrast(gspca_dev);
980 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
982 struct sd *sd = (struct sd *) gspca_dev;
988 /* sub-driver description */
989 static struct sd_desc sd_desc = {
992 .nctrls = ARRAY_SIZE(sd_ctrls),
997 .pkt_scan = sd_pkt_scan,
1000 /* -- module initialisation -- */
1001 static __devinitdata struct usb_device_id device_table[] = {
1002 {USB_DEVICE(0x0572, 0x0041)},
1005 MODULE_DEVICE_TABLE(usb, device_table);
1007 /* -- device connect -- */
1008 static int sd_probe(struct usb_interface *intf,
1009 const struct usb_device_id *id)
1011 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1015 static struct usb_driver sd_driver = {
1016 .name = MODULE_NAME,
1017 .id_table = device_table,
1019 .disconnect = gspca_disconnect,
1021 .suspend = gspca_suspend,
1022 .resume = gspca_resume,
1026 /* -- module insert / remove -- */
1027 static int __init sd_mod_init(void)
1029 if (usb_register(&sd_driver) < 0)
1031 PDEBUG(D_PROBE, "registered");
1034 static void __exit sd_mod_exit(void)
1036 usb_deregister(&sd_driver);
1037 PDEBUG(D_PROBE, "deregistered");
1040 module_init(sd_mod_init);
1041 module_exit(sd_mod_exit);