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