1/* 2 * Sunplus spca504(abc) spca533 spca536 library 3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr 4 * 5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 6 * 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 10 * any later version. 11 * 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. 16 * 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 20 */ 21 22#define MODULE_NAME "sunplus" 23 24#include "gspca.h" 25#include "jpeg.h" 26 27MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 28MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); 29MODULE_LICENSE("GPL"); 30 31/* specific webcam descriptor */ 32struct sd { 33 struct gspca_dev gspca_dev; /* !! must be the first item */ 34 35 s8 brightness; 36 u8 contrast; 37 u8 colors; 38 u8 autogain; 39 u8 quality; 40#define QUALITY_MIN 70 41#define QUALITY_MAX 95 42#define QUALITY_DEF 85 43 44 u8 bridge; 45#define BRIDGE_SPCA504 0 46#define BRIDGE_SPCA504B 1 47#define BRIDGE_SPCA504C 2 48#define BRIDGE_SPCA533 3 49#define BRIDGE_SPCA536 4 50 u8 subtype; 51#define AiptekMiniPenCam13 1 52#define LogitechClickSmart420 2 53#define LogitechClickSmart820 3 54#define MegapixV4 4 55#define MegaImageVI 5 56 57 u8 jpeg_hdr[JPEG_HDR_SZ]; 58}; 59 60/* V4L2 controls supported by the driver */ 61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); 69 70static const struct ctrl sd_ctrls[] = { 71 { 72 { 73 .id = V4L2_CID_BRIGHTNESS, 74 .type = V4L2_CTRL_TYPE_INTEGER, 75 .name = "Brightness", 76 .minimum = -128, 77 .maximum = 127, 78 .step = 1, 79#define BRIGHTNESS_DEF 0 80 .default_value = BRIGHTNESS_DEF, 81 }, 82 .set = sd_setbrightness, 83 .get = sd_getbrightness, 84 }, 85 { 86 { 87 .id = V4L2_CID_CONTRAST, 88 .type = V4L2_CTRL_TYPE_INTEGER, 89 .name = "Contrast", 90 .minimum = 0, 91 .maximum = 0xff, 92 .step = 1, 93#define CONTRAST_DEF 0x20 94 .default_value = CONTRAST_DEF, 95 }, 96 .set = sd_setcontrast, 97 .get = sd_getcontrast, 98 }, 99 { 100 { 101 .id = V4L2_CID_SATURATION, 102 .type = V4L2_CTRL_TYPE_INTEGER, 103 .name = "Color", 104 .minimum = 0, 105 .maximum = 0xff, 106 .step = 1, 107#define COLOR_DEF 0x1a 108 .default_value = COLOR_DEF, 109 }, 110 .set = sd_setcolors, 111 .get = sd_getcolors, 112 }, 113 { 114 { 115 .id = V4L2_CID_AUTOGAIN, 116 .type = V4L2_CTRL_TYPE_BOOLEAN, 117 .name = "Auto Gain", 118 .minimum = 0, 119 .maximum = 1, 120 .step = 1, 121#define AUTOGAIN_DEF 1 122 .default_value = AUTOGAIN_DEF, 123 }, 124 .set = sd_setautogain, 125 .get = sd_getautogain, 126 }, 127}; 128 129static const struct v4l2_pix_format vga_mode[] = { 130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 131 .bytesperline = 320, 132 .sizeimage = 320 * 240 * 3 / 8 + 590, 133 .colorspace = V4L2_COLORSPACE_JPEG, 134 .priv = 2}, 135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 136 .bytesperline = 640, 137 .sizeimage = 640 * 480 * 3 / 8 + 590, 138 .colorspace = V4L2_COLORSPACE_JPEG, 139 .priv = 1}, 140}; 141 142static const struct v4l2_pix_format custom_mode[] = { 143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 144 .bytesperline = 320, 145 .sizeimage = 320 * 240 * 3 / 8 + 590, 146 .colorspace = V4L2_COLORSPACE_JPEG, 147 .priv = 2}, 148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 149 .bytesperline = 464, 150 .sizeimage = 464 * 480 * 3 / 8 + 590, 151 .colorspace = V4L2_COLORSPACE_JPEG, 152 .priv = 1}, 153}; 154 155static const struct v4l2_pix_format vga_mode2[] = { 156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 157 .bytesperline = 176, 158 .sizeimage = 176 * 144 * 3 / 8 + 590, 159 .colorspace = V4L2_COLORSPACE_JPEG, 160 .priv = 4}, 161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 162 .bytesperline = 320, 163 .sizeimage = 320 * 240 * 3 / 8 + 590, 164 .colorspace = V4L2_COLORSPACE_JPEG, 165 .priv = 3}, 166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 167 .bytesperline = 352, 168 .sizeimage = 352 * 288 * 3 / 8 + 590, 169 .colorspace = V4L2_COLORSPACE_JPEG, 170 .priv = 2}, 171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 172 .bytesperline = 640, 173 .sizeimage = 640 * 480 * 3 / 8 + 590, 174 .colorspace = V4L2_COLORSPACE_JPEG, 175 .priv = 1}, 176}; 177 178#define SPCA50X_OFFSET_DATA 10 179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3 180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4 181#define SPCA504_PCCAM600_OFFSET_MODE 5 182#define SPCA504_PCCAM600_OFFSET_DATA 14 183 /* Frame packet header offsets for the spca533 */ 184#define SPCA533_OFFSET_DATA 16 185#define SPCA533_OFFSET_FRAMSEQ 15 186/* Frame packet header offsets for the spca536 */ 187#define SPCA536_OFFSET_DATA 4 188#define SPCA536_OFFSET_FRAMSEQ 1 189 190struct cmd { 191 u8 req; 192 u16 val; 193 u16 idx; 194}; 195 196/* Initialisation data for the Creative PC-CAM 600 */ 197static const struct cmd spca504_pccam600_init_data[] = { 198/* {0xa0, 0x0000, 0x0503}, * capture mode */ 199 {0x00, 0x0000, 0x2000}, 200 {0x00, 0x0013, 0x2301}, 201 {0x00, 0x0003, 0x2000}, 202 {0x00, 0x0001, 0x21ac}, 203 {0x00, 0x0001, 0x21a6}, 204 {0x00, 0x0000, 0x21a7}, /* brightness */ 205 {0x00, 0x0020, 0x21a8}, /* contrast */ 206 {0x00, 0x0001, 0x21ac}, /* sat/hue */ 207 {0x00, 0x0000, 0x21ad}, /* hue */ 208 {0x00, 0x001a, 0x21ae}, /* saturation */ 209 {0x00, 0x0002, 0x21a3}, /* gamma */ 210 {0x30, 0x0154, 0x0008}, 211 {0x30, 0x0004, 0x0006}, 212 {0x30, 0x0258, 0x0009}, 213 {0x30, 0x0004, 0x0000}, 214 {0x30, 0x0093, 0x0004}, 215 {0x30, 0x0066, 0x0005}, 216 {0x00, 0x0000, 0x2000}, 217 {0x00, 0x0013, 0x2301}, 218 {0x00, 0x0003, 0x2000}, 219 {0x00, 0x0013, 0x2301}, 220 {0x00, 0x0003, 0x2000}, 221}; 222 223/* Creative PC-CAM 600 specific open data, sent before using the 224 * generic initialisation data from spca504_open_data. 225 */ 226static const struct cmd spca504_pccam600_open_data[] = { 227 {0x00, 0x0001, 0x2501}, 228 {0x20, 0x0500, 0x0001}, /* snapshot mode */ 229 {0x00, 0x0003, 0x2880}, 230 {0x00, 0x0001, 0x2881}, 231}; 232 233/* Initialisation data for the logitech clicksmart 420 */ 234static const struct cmd spca504A_clicksmart420_init_data[] = { 235/* {0xa0, 0x0000, 0x0503}, * capture mode */ 236 {0x00, 0x0000, 0x2000}, 237 {0x00, 0x0013, 0x2301}, 238 {0x00, 0x0003, 0x2000}, 239 {0x00, 0x0001, 0x21ac}, 240 {0x00, 0x0001, 0x21a6}, 241 {0x00, 0x0000, 0x21a7}, /* brightness */ 242 {0x00, 0x0020, 0x21a8}, /* contrast */ 243 {0x00, 0x0001, 0x21ac}, /* sat/hue */ 244 {0x00, 0x0000, 0x21ad}, /* hue */ 245 {0x00, 0x001a, 0x21ae}, /* saturation */ 246 {0x00, 0x0002, 0x21a3}, /* gamma */ 247 {0x30, 0x0004, 0x000a}, 248 {0xb0, 0x0001, 0x0000}, 249 250 251 {0xa1, 0x0080, 0x0001}, 252 {0x30, 0x0049, 0x0000}, 253 {0x30, 0x0060, 0x0005}, 254 {0x0c, 0x0004, 0x0000}, 255 {0x00, 0x0000, 0x0000}, 256 {0x00, 0x0000, 0x2000}, 257 {0x00, 0x0013, 0x2301}, 258 {0x00, 0x0003, 0x2000}, 259 {0x00, 0x0000, 0x2000}, 260 261}; 262 263/* clicksmart 420 open data ? */ 264static const struct cmd spca504A_clicksmart420_open_data[] = { 265 {0x00, 0x0001, 0x2501}, 266 {0x20, 0x0502, 0x0000}, 267 {0x06, 0x0000, 0x0000}, 268 {0x00, 0x0004, 0x2880}, 269 {0x00, 0x0001, 0x2881}, 270 271 {0xa0, 0x0000, 0x0503}, 272}; 273 274static const u8 qtable_creative_pccam[2][64] = { 275 { /* Q-table Y-components */ 276 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 277 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, 278 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, 279 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, 280 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, 281 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, 282 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, 283 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e}, 284 { /* Q-table C-components */ 285 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 286 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 287 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 288 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 290 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 291 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 292 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} 293}; 294 295static const u8 qtable_spca504_default[2][64] = { 296 { /* Q-table Y-components */ 297 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 298 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, 299 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11, 300 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13, 301 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17, 302 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c, 303 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e, 304 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e, 305 }, 306 { /* Q-table C-components */ 307 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e, 308 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 309 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 310 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 311 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 312 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 313 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} 315}; 316 317/* read <len> bytes to gspca_dev->usb_buf */ 318static void reg_r(struct gspca_dev *gspca_dev, 319 u8 req, 320 u16 index, 321 u16 len) 322{ 323 int ret; 324 325#ifdef GSPCA_DEBUG 326 if (len > USB_BUF_SZ) { 327 err("reg_r: buffer overflow"); 328 return; 329 } 330#endif 331 if (gspca_dev->usb_err < 0) 332 return; 333 ret = usb_control_msg(gspca_dev->dev, 334 usb_rcvctrlpipe(gspca_dev->dev, 0), 335 req, 336 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 337 0, /* value */ 338 index, 339 len ? gspca_dev->usb_buf : NULL, len, 340 500); 341 if (ret < 0) { 342 PDEBUG(D_ERR, "reg_r err %d", ret); 343 gspca_dev->usb_err = ret; 344 } 345} 346 347/* write one byte */ 348static void reg_w_1(struct gspca_dev *gspca_dev, 349 u8 req, 350 u16 value, 351 u16 index, 352 u16 byte) 353{ 354 int ret; 355 356 if (gspca_dev->usb_err < 0) 357 return; 358 gspca_dev->usb_buf[0] = byte; 359 ret = usb_control_msg(gspca_dev->dev, 360 usb_sndctrlpipe(gspca_dev->dev, 0), 361 req, 362 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 363 value, index, 364 gspca_dev->usb_buf, 1, 365 500); 366 if (ret < 0) { 367 PDEBUG(D_ERR, "reg_w_1 err %d", ret); 368 gspca_dev->usb_err = ret; 369 } 370} 371 372/* write req / index / value */ 373static void reg_w_riv(struct gspca_dev *gspca_dev, 374 u8 req, u16 index, u16 value) 375{ 376 struct usb_device *dev = gspca_dev->dev; 377 int ret; 378 379 if (gspca_dev->usb_err < 0) 380 return; 381 ret = usb_control_msg(dev, 382 usb_sndctrlpipe(dev, 0), 383 req, 384 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 385 value, index, NULL, 0, 500); 386 if (ret < 0) { 387 PDEBUG(D_ERR, "reg_w_riv err %d", ret); 388 gspca_dev->usb_err = ret; 389 return; 390 } 391 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x", 392 req, index, value); 393} 394 395/* read 1 byte */ 396static u8 reg_r_1(struct gspca_dev *gspca_dev, 397 u16 value) /* wValue */ 398{ 399 int ret; 400 401 if (gspca_dev->usb_err < 0) 402 return 0; 403 ret = usb_control_msg(gspca_dev->dev, 404 usb_rcvctrlpipe(gspca_dev->dev, 0), 405 0x20, /* request */ 406 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 407 value, 408 0, /* index */ 409 gspca_dev->usb_buf, 1, 410 500); /* timeout */ 411 if (ret < 0) { 412 PDEBUG(D_ERR, "reg_r_1 err %d", ret); 413 gspca_dev->usb_err = ret; 414 return 0; 415 } 416 return gspca_dev->usb_buf[0]; 417} 418 419/* read 1 or 2 bytes */ 420static u16 reg_r_12(struct gspca_dev *gspca_dev, 421 u8 req, /* bRequest */ 422 u16 index, /* wIndex */ 423 u16 length) /* wLength (1 or 2 only) */ 424{ 425 int ret; 426 427 if (gspca_dev->usb_err < 0) 428 return 0; 429 gspca_dev->usb_buf[1] = 0; 430 ret = usb_control_msg(gspca_dev->dev, 431 usb_rcvctrlpipe(gspca_dev->dev, 0), 432 req, 433 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 434 0, /* value */ 435 index, 436 gspca_dev->usb_buf, length, 437 500); 438 if (ret < 0) { 439 PDEBUG(D_ERR, "reg_r_12 err %d", ret); 440 gspca_dev->usb_err = ret; 441 return 0; 442 } 443 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; 444} 445 446static void write_vector(struct gspca_dev *gspca_dev, 447 const struct cmd *data, int ncmds) 448{ 449 while (--ncmds >= 0) { 450 reg_w_riv(gspca_dev, data->req, data->idx, data->val); 451 data++; 452 } 453} 454 455static void setup_qtable(struct gspca_dev *gspca_dev, 456 const u8 qtable[2][64]) 457{ 458 int i; 459 460 /* loop over y components */ 461 for (i = 0; i < 64; i++) 462 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]); 463 464 /* loop over c components */ 465 for (i = 0; i < 64; i++) 466 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]); 467} 468 469static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, 470 u8 req, u16 idx, u16 val) 471{ 472 u16 notdone; 473 474 reg_w_riv(gspca_dev, req, idx, val); 475 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); 476 reg_w_riv(gspca_dev, req, idx, val); 477 478 PDEBUG(D_FRAM, "before wait 0x%04x", notdone); 479 480 msleep(200); 481 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); 482 PDEBUG(D_FRAM, "after wait 0x%04x", notdone); 483} 484 485static void spca504_read_info(struct gspca_dev *gspca_dev) 486{ 487 int i; 488 u8 info[6]; 489 490 for (i = 0; i < 6; i++) 491 info[i] = reg_r_1(gspca_dev, i); 492 PDEBUG(D_STREAM, 493 "Read info: %d %d %d %d %d %d." 494 " Should be 1,0,2,2,0,0", 495 info[0], info[1], info[2], 496 info[3], info[4], info[5]); 497} 498 499static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, 500 u8 req, 501 u16 idx, u16 val, u16 endcode, u8 count) 502{ 503 u16 status; 504 505 reg_w_riv(gspca_dev, req, idx, val); 506 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); 507 if (gspca_dev->usb_err < 0) 508 return; 509 PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode); 510 if (!count) 511 return; 512 count = 200; 513 while (--count > 0) { 514 msleep(10); 515 /* gsmart mini2 write a each wait setting 1 ms is enough */ 516/* reg_w_riv(gspca_dev, req, idx, val); */ 517 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); 518 if (status == endcode) { 519 PDEBUG(D_FRAM, "status 0x%04x after wait %d", 520 status, 200 - count); 521 break; 522 } 523 } 524} 525 526static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev) 527{ 528 int count = 10; 529 530 while (--count > 0) { 531 reg_r(gspca_dev, 0x21, 0, 1); 532 if ((gspca_dev->usb_buf[0] & 0x01) == 0) 533 break; 534 msleep(10); 535 } 536} 537 538static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) 539{ 540 int count = 50; 541 542 while (--count > 0) { 543 reg_r(gspca_dev, 0x21, 1, 1); 544 if (gspca_dev->usb_buf[0] != 0) { 545 reg_w_1(gspca_dev, 0x21, 0, 1, 0); 546 reg_r(gspca_dev, 0x21, 1, 1); 547 spca504B_PollingDataReady(gspca_dev); 548 break; 549 } 550 msleep(10); 551 } 552} 553 554static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) 555{ 556 u8 *data; 557 558 data = gspca_dev->usb_buf; 559 reg_r(gspca_dev, 0x20, 0, 5); 560 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ", 561 data[0], data[1], data[2], data[3], data[4]); 562 reg_r(gspca_dev, 0x23, 0, 64); 563 reg_r(gspca_dev, 0x23, 1, 64); 564} 565 566static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) 567{ 568 struct sd *sd = (struct sd *) gspca_dev; 569 u8 Size; 570 571 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 572 switch (sd->bridge) { 573 case BRIDGE_SPCA533: 574 reg_w_riv(gspca_dev, 0x31, 0, 0); 575 spca504B_WaitCmdStatus(gspca_dev); 576 spca504B_PollingDataReady(gspca_dev); 577 spca50x_GetFirmware(gspca_dev); 578 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ 579 reg_r(gspca_dev, 0x24, 8, 1); 580 581 reg_w_1(gspca_dev, 0x25, 0, 4, Size); 582 reg_r(gspca_dev, 0x25, 4, 1); /* size */ 583 spca504B_PollingDataReady(gspca_dev); 584 585 /* Init the cam width height with some values get on init ? */ 586 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); 587 spca504B_WaitCmdStatus(gspca_dev); 588 spca504B_PollingDataReady(gspca_dev); 589 break; 590 default: 591/* case BRIDGE_SPCA504B: */ 592/* case BRIDGE_SPCA536: */ 593 reg_w_1(gspca_dev, 0x25, 0, 4, Size); 594 reg_r(gspca_dev, 0x25, 4, 1); /* size */ 595 reg_w_1(gspca_dev, 0x27, 0, 0, 6); 596 reg_r(gspca_dev, 0x27, 0, 1); /* type */ 597 spca504B_PollingDataReady(gspca_dev); 598 break; 599 case BRIDGE_SPCA504: 600 Size += 3; 601 if (sd->subtype == AiptekMiniPenCam13) { 602 /* spca504a aiptek */ 603 spca504A_acknowledged_command(gspca_dev, 604 0x08, Size, 0, 605 0x80 | (Size & 0x0f), 1); 606 spca504A_acknowledged_command(gspca_dev, 607 1, 3, 0, 0x9f, 0); 608 } else { 609 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0); 610 } 611 break; 612 case BRIDGE_SPCA504C: 613 /* capture mode */ 614 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); 615 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); 616 break; 617 } 618} 619 620static void spca504_wait_status(struct gspca_dev *gspca_dev) 621{ 622 int cnt; 623 624 cnt = 256; 625 while (--cnt > 0) { 626 /* With this we get the status, when return 0 it's all ok */ 627 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0) 628 return; 629 msleep(10); 630 } 631} 632 633static void spca504B_setQtable(struct gspca_dev *gspca_dev) 634{ 635 reg_w_1(gspca_dev, 0x26, 0, 0, 3); 636 reg_r(gspca_dev, 0x26, 0, 1); 637 spca504B_PollingDataReady(gspca_dev); 638} 639 640static void setbrightness(struct gspca_dev *gspca_dev) 641{ 642 struct sd *sd = (struct sd *) gspca_dev; 643 u16 reg; 644 645 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; 646 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness); 647} 648 649static void setcontrast(struct gspca_dev *gspca_dev) 650{ 651 struct sd *sd = (struct sd *) gspca_dev; 652 u16 reg; 653 654 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; 655 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast); 656} 657 658static void setcolors(struct gspca_dev *gspca_dev) 659{ 660 struct sd *sd = (struct sd *) gspca_dev; 661 u16 reg; 662 663 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; 664 reg_w_riv(gspca_dev, 0x00, reg, sd->colors); 665} 666 667static void init_ctl_reg(struct gspca_dev *gspca_dev) 668{ 669 struct sd *sd = (struct sd *) gspca_dev; 670 int pollreg = 1; 671 672 setbrightness(gspca_dev); 673 setcontrast(gspca_dev); 674 setcolors(gspca_dev); 675 676 switch (sd->bridge) { 677 case BRIDGE_SPCA504: 678 case BRIDGE_SPCA504C: 679 pollreg = 0; 680 /* fall thru */ 681 default: 682/* case BRIDGE_SPCA533: */ 683/* case BRIDGE_SPCA504B: */ 684 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ 685 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ 686 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ 687 break; 688 case BRIDGE_SPCA536: 689 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); 690 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); 691 reg_w_riv(gspca_dev, 0, 0x2089, 0x00); 692 break; 693 } 694 if (pollreg) 695 spca504B_PollingDataReady(gspca_dev); 696} 697 698/* this function is called at probe time */ 699static int sd_config(struct gspca_dev *gspca_dev, 700 const struct usb_device_id *id) 701{ 702 struct sd *sd = (struct sd *) gspca_dev; 703 struct cam *cam; 704 705 cam = &gspca_dev->cam; 706 707 sd->bridge = id->driver_info >> 8; 708 sd->subtype = id->driver_info; 709 710 if (sd->subtype == AiptekMiniPenCam13) { 711/* try to get the firmware as some cam answer 2.0.1.2.2 712 * and should be a spca504b then overwrite that setting */ 713 reg_r(gspca_dev, 0x20, 0, 1); 714 switch (gspca_dev->usb_buf[0]) { 715 case 1: 716 break; /* (right bridge/subtype) */ 717 case 2: 718 sd->bridge = BRIDGE_SPCA504B; 719 sd->subtype = 0; 720 break; 721 default: 722 return -ENODEV; 723 } 724 } 725 726 switch (sd->bridge) { 727 default: 728/* case BRIDGE_SPCA504B: */ 729/* case BRIDGE_SPCA504: */ 730/* case BRIDGE_SPCA536: */ 731 cam->cam_mode = vga_mode; 732 cam->nmodes =ARRAY_SIZE(vga_mode); 733 break; 734 case BRIDGE_SPCA533: 735 cam->cam_mode = custom_mode; 736 if (sd->subtype == MegaImageVI) /* 320x240 only */ 737 cam->nmodes = ARRAY_SIZE(custom_mode) - 1; 738 else 739 cam->nmodes = ARRAY_SIZE(custom_mode); 740 break; 741 case BRIDGE_SPCA504C: 742 cam->cam_mode = vga_mode2; 743 cam->nmodes = ARRAY_SIZE(vga_mode2); 744 break; 745 } 746 sd->brightness = BRIGHTNESS_DEF; 747 sd->contrast = CONTRAST_DEF; 748 sd->colors = COLOR_DEF; 749 sd->autogain = AUTOGAIN_DEF; 750 sd->quality = QUALITY_DEF; 751 return 0; 752} 753 754/* this function is called at probe and resume time */ 755static int sd_init(struct gspca_dev *gspca_dev) 756{ 757 struct sd *sd = (struct sd *) gspca_dev; 758 759 switch (sd->bridge) { 760 case BRIDGE_SPCA504B: 761 reg_w_riv(gspca_dev, 0x1d, 0x00, 0); 762 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); 763 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); 764 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); 765 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); 766 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); 767 /* fall thru */ 768 case BRIDGE_SPCA533: 769 spca504B_PollingDataReady(gspca_dev); 770 spca50x_GetFirmware(gspca_dev); 771 break; 772 case BRIDGE_SPCA536: 773 spca50x_GetFirmware(gspca_dev); 774 reg_r(gspca_dev, 0x00, 0x5002, 1); 775 reg_w_1(gspca_dev, 0x24, 0, 0, 0); 776 reg_r(gspca_dev, 0x24, 0, 1); 777 spca504B_PollingDataReady(gspca_dev); 778 reg_w_riv(gspca_dev, 0x34, 0, 0); 779 spca504B_WaitCmdStatus(gspca_dev); 780 break; 781 case BRIDGE_SPCA504C: /* pccam600 */ 782 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)"); 783 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000); 784 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */ 785 spca504_wait_status(gspca_dev); 786 if (sd->subtype == LogitechClickSmart420) 787 write_vector(gspca_dev, 788 spca504A_clicksmart420_open_data, 789 ARRAY_SIZE(spca504A_clicksmart420_open_data)); 790 else 791 write_vector(gspca_dev, spca504_pccam600_open_data, 792 ARRAY_SIZE(spca504_pccam600_open_data)); 793 setup_qtable(gspca_dev, qtable_creative_pccam); 794 break; 795 default: 796/* case BRIDGE_SPCA504: */ 797 PDEBUG(D_STREAM, "Opening SPCA504"); 798 if (sd->subtype == AiptekMiniPenCam13) { 799 spca504_read_info(gspca_dev); 800 801 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ 802 spca504A_acknowledged_command(gspca_dev, 0x24, 803 8, 3, 0x9e, 1); 804 /* Twice sequential need status 0xff->0x9e->0x9d */ 805 spca504A_acknowledged_command(gspca_dev, 0x24, 806 8, 3, 0x9e, 0); 807 808 spca504A_acknowledged_command(gspca_dev, 0x24, 809 0, 0, 0x9d, 1); 810 /******************************/ 811 /* spca504a aiptek */ 812 spca504A_acknowledged_command(gspca_dev, 0x08, 813 6, 0, 0x86, 1); 814/* reg_write (dev, 0, 0x2000, 0); */ 815/* reg_write (dev, 0, 0x2883, 1); */ 816/* spca504A_acknowledged_command (gspca_dev, 0x08, 817 6, 0, 0x86, 1); */ 818/* spca504A_acknowledged_command (gspca_dev, 0x24, 819 0, 0, 0x9D, 1); */ 820 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); 821 /* L92 sno1t.txt */ 822 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); 823 spca504A_acknowledged_command(gspca_dev, 0x01, 824 0x0f, 0, 0xff, 0); 825 } 826 /* setup qtable */ 827 reg_w_riv(gspca_dev, 0, 0x2000, 0); 828 reg_w_riv(gspca_dev, 0, 0x2883, 1); 829 setup_qtable(gspca_dev, qtable_spca504_default); 830 break; 831 } 832 return gspca_dev->usb_err; 833} 834 835static int sd_start(struct gspca_dev *gspca_dev) 836{ 837 struct sd *sd = (struct sd *) gspca_dev; 838 int enable; 839 840 /* create the JPEG header */ 841 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 842 0x22); /* JPEG 411 */ 843 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 844 845 if (sd->bridge == BRIDGE_SPCA504B) 846 spca504B_setQtable(gspca_dev); 847 spca504B_SetSizeType(gspca_dev); 848 switch (sd->bridge) { 849 default: 850/* case BRIDGE_SPCA504B: */ 851/* case BRIDGE_SPCA533: */ 852/* case BRIDGE_SPCA536: */ 853 switch (sd->subtype) { 854 case MegapixV4: 855 case LogitechClickSmart820: 856 case MegaImageVI: 857 reg_w_riv(gspca_dev, 0xf0, 0, 0); 858 spca504B_WaitCmdStatus(gspca_dev); 859 reg_r(gspca_dev, 0xf0, 4, 0); 860 spca504B_WaitCmdStatus(gspca_dev); 861 break; 862 default: 863 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); 864 spca504B_WaitCmdStatus(gspca_dev); 865 spca504B_PollingDataReady(gspca_dev); 866 break; 867 } 868 break; 869 case BRIDGE_SPCA504: 870 if (sd->subtype == AiptekMiniPenCam13) { 871 spca504_read_info(gspca_dev); 872 873 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ 874 spca504A_acknowledged_command(gspca_dev, 0x24, 875 8, 3, 0x9e, 1); 876 /* Twice sequential need status 0xff->0x9e->0x9d */ 877 spca504A_acknowledged_command(gspca_dev, 0x24, 878 8, 3, 0x9e, 0); 879 spca504A_acknowledged_command(gspca_dev, 0x24, 880 0, 0, 0x9d, 1); 881 } else { 882 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); 883 spca504_read_info(gspca_dev); 884 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); 885 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); 886 } 887 spca504B_SetSizeType(gspca_dev); 888 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); 889 /* L92 sno1t.txt */ 890 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); 891 break; 892 case BRIDGE_SPCA504C: 893 if (sd->subtype == LogitechClickSmart420) { 894 write_vector(gspca_dev, 895 spca504A_clicksmart420_init_data, 896 ARRAY_SIZE(spca504A_clicksmart420_init_data)); 897 } else { 898 write_vector(gspca_dev, spca504_pccam600_init_data, 899 ARRAY_SIZE(spca504_pccam600_init_data)); 900 } 901 enable = (sd->autogain ? 0x04 : 0x01); 902 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable); 903 /* auto exposure */ 904 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable); 905 /* auto whiteness */ 906 907 /* set default exposure compensation and whiteness balance */ 908 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */ 909 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600); 910 spca504B_SetSizeType(gspca_dev); 911 break; 912 } 913 init_ctl_reg(gspca_dev); 914 return gspca_dev->usb_err; 915} 916 917static void sd_stopN(struct gspca_dev *gspca_dev) 918{ 919 struct sd *sd = (struct sd *) gspca_dev; 920 921 switch (sd->bridge) { 922 default: 923/* case BRIDGE_SPCA533: */ 924/* case BRIDGE_SPCA536: */ 925/* case BRIDGE_SPCA504B: */ 926 reg_w_riv(gspca_dev, 0x31, 0, 0); 927 spca504B_WaitCmdStatus(gspca_dev); 928 spca504B_PollingDataReady(gspca_dev); 929 break; 930 case BRIDGE_SPCA504: 931 case BRIDGE_SPCA504C: 932 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000); 933 934 if (sd->subtype == AiptekMiniPenCam13) { 935 /* spca504a aiptek */ 936/* spca504A_acknowledged_command(gspca_dev, 0x08, 937 6, 0, 0x86, 1); */ 938 spca504A_acknowledged_command(gspca_dev, 0x24, 939 0x00, 0x00, 0x9d, 1); 940 spca504A_acknowledged_command(gspca_dev, 0x01, 941 0x0f, 0x00, 0xff, 1); 942 } else { 943 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); 944 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000); 945 } 946 break; 947 } 948} 949 950static void sd_pkt_scan(struct gspca_dev *gspca_dev, 951 u8 *data, /* isoc packet */ 952 int len) /* iso packet length */ 953{ 954 struct sd *sd = (struct sd *) gspca_dev; 955 int i, sof = 0; 956 static u8 ffd9[] = {0xff, 0xd9}; 957 958/* frames are jpeg 4.1.1 without 0xff escape */ 959 switch (sd->bridge) { 960 case BRIDGE_SPCA533: 961 if (data[0] == 0xff) { 962 if (data[1] != 0x01) { /* drop packet */ 963/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 964 return; 965 } 966 sof = 1; 967 data += SPCA533_OFFSET_DATA; 968 len -= SPCA533_OFFSET_DATA; 969 } else { 970 data += 1; 971 len -= 1; 972 } 973 break; 974 case BRIDGE_SPCA536: 975 if (data[0] == 0xff) { 976 sof = 1; 977 data += SPCA536_OFFSET_DATA; 978 len -= SPCA536_OFFSET_DATA; 979 } else { 980 data += 2; 981 len -= 2; 982 } 983 break; 984 default: 985/* case BRIDGE_SPCA504: */ 986/* case BRIDGE_SPCA504B: */ 987 switch (data[0]) { 988 case 0xfe: /* start of frame */ 989 sof = 1; 990 data += SPCA50X_OFFSET_DATA; 991 len -= SPCA50X_OFFSET_DATA; 992 break; 993 case 0xff: /* drop packet */ 994/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 995 return; 996 default: 997 data += 1; 998 len -= 1; 999 break; 1000 } 1001 break; 1002 case BRIDGE_SPCA504C: 1003 switch (data[0]) { 1004 case 0xfe: /* start of frame */ 1005 sof = 1; 1006 data += SPCA504_PCCAM600_OFFSET_DATA; 1007 len -= SPCA504_PCCAM600_OFFSET_DATA; 1008 break; 1009 case 0xff: /* drop packet */ 1010/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 1011 return; 1012 default: 1013 data += 1; 1014 len -= 1; 1015 break; 1016 } 1017 break; 1018 } 1019 if (sof) { /* start of frame */ 1020 gspca_frame_add(gspca_dev, LAST_PACKET, 1021 ffd9, 2); 1022 1023 /* put the JPEG header in the new frame */ 1024 gspca_frame_add(gspca_dev, FIRST_PACKET, 1025 sd->jpeg_hdr, JPEG_HDR_SZ); 1026 } 1027 1028 /* add 0x00 after 0xff */ 1029 i = 0; 1030 do { 1031 if (data[i] == 0xff) { 1032 gspca_frame_add(gspca_dev, INTER_PACKET, 1033 data, i + 1); 1034 len -= i; 1035 data += i; 1036 *data = 0x00; 1037 i = 0; 1038 } 1039 i++; 1040 } while (i < len); 1041 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 1042} 1043 1044static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 1045{ 1046 struct sd *sd = (struct sd *) gspca_dev; 1047 1048 sd->brightness = val; 1049 if (gspca_dev->streaming) 1050 setbrightness(gspca_dev); 1051 return gspca_dev->usb_err; 1052} 1053 1054static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 1055{ 1056 struct sd *sd = (struct sd *) gspca_dev; 1057 1058 *val = sd->brightness; 1059 return 0; 1060} 1061 1062static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 1063{ 1064 struct sd *sd = (struct sd *) gspca_dev; 1065 1066 sd->contrast = val; 1067 if (gspca_dev->streaming) 1068 setcontrast(gspca_dev); 1069 return gspca_dev->usb_err; 1070} 1071 1072static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 1073{ 1074 struct sd *sd = (struct sd *) gspca_dev; 1075 1076 *val = sd->contrast; 1077 return 0; 1078} 1079 1080static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 1081{ 1082 struct sd *sd = (struct sd *) gspca_dev; 1083 1084 sd->colors = val; 1085 if (gspca_dev->streaming) 1086 setcolors(gspca_dev); 1087 return gspca_dev->usb_err; 1088} 1089 1090static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 1091{ 1092 struct sd *sd = (struct sd *) gspca_dev; 1093 1094 *val = sd->colors; 1095 return 0; 1096} 1097 1098static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) 1099{ 1100 struct sd *sd = (struct sd *) gspca_dev; 1101 1102 sd->autogain = val; 1103 return 0; 1104} 1105 1106static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) 1107{ 1108 struct sd *sd = (struct sd *) gspca_dev; 1109 1110 *val = sd->autogain; 1111 return 0; 1112} 1113 1114static int sd_set_jcomp(struct gspca_dev *gspca_dev, 1115 struct v4l2_jpegcompression *jcomp) 1116{ 1117 struct sd *sd = (struct sd *) gspca_dev; 1118 1119 if (jcomp->quality < QUALITY_MIN) 1120 sd->quality = QUALITY_MIN; 1121 else if (jcomp->quality > QUALITY_MAX) 1122 sd->quality = QUALITY_MAX; 1123 else 1124 sd->quality = jcomp->quality; 1125 if (gspca_dev->streaming) 1126 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 1127 return gspca_dev->usb_err; 1128} 1129 1130static int sd_get_jcomp(struct gspca_dev *gspca_dev, 1131 struct v4l2_jpegcompression *jcomp) 1132{ 1133 struct sd *sd = (struct sd *) gspca_dev; 1134 1135 memset(jcomp, 0, sizeof *jcomp); 1136 jcomp->quality = sd->quality; 1137 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 1138 | V4L2_JPEG_MARKER_DQT; 1139 return 0; 1140} 1141 1142/* sub-driver description */ 1143static const struct sd_desc sd_desc = { 1144 .name = MODULE_NAME, 1145 .ctrls = sd_ctrls, 1146 .nctrls = ARRAY_SIZE(sd_ctrls), 1147 .config = sd_config, 1148 .init = sd_init, 1149 .start = sd_start, 1150 .stopN = sd_stopN, 1151 .pkt_scan = sd_pkt_scan, 1152 .get_jcomp = sd_get_jcomp, 1153 .set_jcomp = sd_set_jcomp, 1154}; 1155 1156/* -- module initialisation -- */ 1157#define BS(bridge, subtype) \ 1158 .driver_info = (BRIDGE_ ## bridge << 8) \ 1159 | (subtype) 1160static const __devinitdata struct usb_device_id device_table[] = { 1161 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)}, 1162 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)}, 1163 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)}, 1164 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)}, 1165 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)}, 1166 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)}, 1167 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)}, 1168 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)}, 1169 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)}, 1170 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)}, 1171 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)}, 1172 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)}, 1173 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)}, 1174 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)}, 1175 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)}, 1176 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, 1177 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, 1178 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, 1179 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)}, 1180 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, 1181 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, 1182 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, 1183 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)}, 1184 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)}, 1185 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)}, 1186 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)}, 1187 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)}, 1188 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)}, 1189 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)}, 1190 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)}, 1191 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)}, 1192 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)}, 1193 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)}, 1194 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)}, 1195 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)}, 1196 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)}, 1197 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)}, 1198 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)}, 1199 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)}, 1200 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)}, 1201 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)}, 1202 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)}, 1203 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)}, 1204 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)}, 1205 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)}, 1206 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)}, 1207 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)}, 1208 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)}, 1209 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)}, 1210 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)}, 1211 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)}, 1212 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)}, 1213 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)}, 1214 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)}, 1215 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)}, 1216 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)}, 1217 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)}, 1218 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)}, 1219 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)}, 1220 {} 1221}; 1222MODULE_DEVICE_TABLE(usb, device_table); 1223 1224/* -- device connect -- */ 1225static int sd_probe(struct usb_interface *intf, 1226 const struct usb_device_id *id) 1227{ 1228 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1229 THIS_MODULE); 1230} 1231 1232static struct usb_driver sd_driver = { 1233 .name = MODULE_NAME, 1234 .id_table = device_table, 1235 .probe = sd_probe, 1236 .disconnect = gspca_disconnect, 1237#ifdef CONFIG_PM 1238 .suspend = gspca_suspend, 1239 .resume = gspca_resume, 1240#endif 1241}; 1242 1243/* -- module insert / remove -- */ 1244static int __init sd_mod_init(void) 1245{ 1246 int ret; 1247 ret = usb_register(&sd_driver); 1248 if (ret < 0) 1249 return ret; 1250 PDEBUG(D_PROBE, "registered"); 1251 return 0; 1252} 1253static void __exit sd_mod_exit(void) 1254{ 1255 usb_deregister(&sd_driver); 1256 PDEBUG(D_PROBE, "deregistered"); 1257} 1258 1259module_init(sd_mod_init); 1260module_exit(sd_mod_exit); 1261