1 /* 2 * SN9C2028 library 3 * 4 * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 19 #define MODULE_NAME "sn9c2028" 20 21 #include "gspca.h" 22 23 MODULE_AUTHOR("Theodore Kilgore"); 24 MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); 25 MODULE_LICENSE("GPL"); 26 27 /* specific webcam descriptor */ 28 struct sd { 29 struct gspca_dev gspca_dev; /* !! must be the first item */ 30 u8 sof_read; 31 u16 model; 32 33 #define MIN_AVG_LUM 8500 34 #define MAX_AVG_LUM 10000 35 int avg_lum; 36 u8 avg_lum_l; 37 38 struct { /* autogain and gain control cluster */ 39 struct v4l2_ctrl *autogain; 40 struct v4l2_ctrl *gain; 41 }; 42 }; 43 44 struct init_command { 45 unsigned char instruction[6]; 46 unsigned char to_read; /* length to read. 0 means no reply requested */ 47 }; 48 49 /* How to change the resolution of any of the VGA cams is unknown */ 50 static const struct v4l2_pix_format vga_mode[] = { 51 {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 52 .bytesperline = 640, 53 .sizeimage = 640 * 480 * 3 / 4, 54 .colorspace = V4L2_COLORSPACE_SRGB, 55 .priv = 0}, 56 }; 57 58 /* No way to change the resolution of the CIF cams is known */ 59 static const struct v4l2_pix_format cif_mode[] = { 60 {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 61 .bytesperline = 352, 62 .sizeimage = 352 * 288 * 3 / 4, 63 .colorspace = V4L2_COLORSPACE_SRGB, 64 .priv = 0}, 65 }; 66 67 /* the bytes to write are in gspca_dev->usb_buf */ 68 static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) 69 { 70 int rc; 71 72 PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0], 73 command[1], command[2], command[3], command[4], command[5]); 74 75 memcpy(gspca_dev->usb_buf, command, 6); 76 rc = usb_control_msg(gspca_dev->dev, 77 usb_sndctrlpipe(gspca_dev->dev, 0), 78 USB_REQ_GET_CONFIGURATION, 79 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 80 2, 0, gspca_dev->usb_buf, 6, 500); 81 if (rc < 0) { 82 pr_err("command write [%02x] error %d\n", 83 gspca_dev->usb_buf[0], rc); 84 return rc; 85 } 86 87 return 0; 88 } 89 90 static int sn9c2028_read1(struct gspca_dev *gspca_dev) 91 { 92 int rc; 93 94 rc = usb_control_msg(gspca_dev->dev, 95 usb_rcvctrlpipe(gspca_dev->dev, 0), 96 USB_REQ_GET_STATUS, 97 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 98 1, 0, gspca_dev->usb_buf, 1, 500); 99 if (rc != 1) { 100 pr_err("read1 error %d\n", rc); 101 return (rc < 0) ? rc : -EIO; 102 } 103 PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]); 104 return gspca_dev->usb_buf[0]; 105 } 106 107 static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) 108 { 109 int rc; 110 rc = usb_control_msg(gspca_dev->dev, 111 usb_rcvctrlpipe(gspca_dev->dev, 0), 112 USB_REQ_GET_STATUS, 113 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 114 4, 0, gspca_dev->usb_buf, 4, 500); 115 if (rc != 4) { 116 pr_err("read4 error %d\n", rc); 117 return (rc < 0) ? rc : -EIO; 118 } 119 memcpy(reading, gspca_dev->usb_buf, 4); 120 PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0], 121 reading[1], reading[2], reading[3]); 122 return rc; 123 } 124 125 static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) 126 { 127 int i, status; 128 __u8 reading[4]; 129 130 status = sn9c2028_command(gspca_dev, command); 131 if (status < 0) 132 return status; 133 134 status = -1; 135 for (i = 0; i < 256 && status < 2; i++) 136 status = sn9c2028_read1(gspca_dev); 137 if (status < 0) { 138 pr_err("long command status read error %d\n", status); 139 return status; 140 } 141 142 memset(reading, 0, 4); 143 status = sn9c2028_read4(gspca_dev, reading); 144 if (status < 0) 145 return status; 146 147 /* in general, the first byte of the response is the first byte of 148 * the command, or'ed with 8 */ 149 status = sn9c2028_read1(gspca_dev); 150 if (status < 0) 151 return status; 152 153 return 0; 154 } 155 156 static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) 157 { 158 int err_code; 159 160 err_code = sn9c2028_command(gspca_dev, command); 161 if (err_code < 0) 162 return err_code; 163 164 err_code = sn9c2028_read1(gspca_dev); 165 if (err_code < 0) 166 return err_code; 167 168 return 0; 169 } 170 171 /* this function is called at probe time */ 172 static int sd_config(struct gspca_dev *gspca_dev, 173 const struct usb_device_id *id) 174 { 175 struct sd *sd = (struct sd *) gspca_dev; 176 struct cam *cam = &gspca_dev->cam; 177 178 PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)", 179 id->idVendor, id->idProduct); 180 181 sd->model = id->idProduct; 182 183 switch (sd->model) { 184 case 0x7005: 185 PDEBUG(D_PROBE, "Genius Smart 300 camera"); 186 break; 187 case 0x7003: 188 PDEBUG(D_PROBE, "Genius Videocam Live v2"); 189 break; 190 case 0x8000: 191 PDEBUG(D_PROBE, "DC31VC"); 192 break; 193 case 0x8001: 194 PDEBUG(D_PROBE, "Spy camera"); 195 break; 196 case 0x8003: 197 PDEBUG(D_PROBE, "CIF camera"); 198 break; 199 case 0x8008: 200 PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera"); 201 break; 202 case 0x800a: 203 PDEBUG(D_PROBE, "Vivitar 3350b type camera"); 204 cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; 205 break; 206 } 207 208 switch (sd->model) { 209 case 0x8000: 210 case 0x8001: 211 case 0x8003: 212 cam->cam_mode = cif_mode; 213 cam->nmodes = ARRAY_SIZE(cif_mode); 214 break; 215 default: 216 cam->cam_mode = vga_mode; 217 cam->nmodes = ARRAY_SIZE(vga_mode); 218 } 219 return 0; 220 } 221 222 /* this function is called at probe and resume time */ 223 static int sd_init(struct gspca_dev *gspca_dev) 224 { 225 int status = -1; 226 227 sn9c2028_read1(gspca_dev); 228 sn9c2028_read1(gspca_dev); 229 status = sn9c2028_read1(gspca_dev); 230 231 return (status < 0) ? status : 0; 232 } 233 234 static int run_start_commands(struct gspca_dev *gspca_dev, 235 struct init_command *cam_commands, int n) 236 { 237 int i, err_code = -1; 238 239 for (i = 0; i < n; i++) { 240 switch (cam_commands[i].to_read) { 241 case 4: 242 err_code = sn9c2028_long_command(gspca_dev, 243 cam_commands[i].instruction); 244 break; 245 case 1: 246 err_code = sn9c2028_short_command(gspca_dev, 247 cam_commands[i].instruction); 248 break; 249 case 0: 250 err_code = sn9c2028_command(gspca_dev, 251 cam_commands[i].instruction); 252 break; 253 } 254 if (err_code < 0) 255 return err_code; 256 } 257 return 0; 258 } 259 260 static void set_gain(struct gspca_dev *gspca_dev, s32 g) 261 { 262 struct sd *sd = (struct sd *) gspca_dev; 263 264 struct init_command genius_vcam_live_gain_cmds[] = { 265 {{0x1d, 0x25, 0x10 /* This byte is gain */, 266 0x20, 0xab, 0x00}, 0}, 267 }; 268 if (!gspca_dev->streaming) 269 return; 270 271 switch (sd->model) { 272 case 0x7003: 273 genius_vcam_live_gain_cmds[0].instruction[2] = g; 274 run_start_commands(gspca_dev, genius_vcam_live_gain_cmds, 275 ARRAY_SIZE(genius_vcam_live_gain_cmds)); 276 break; 277 default: 278 break; 279 } 280 } 281 282 static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 283 { 284 struct gspca_dev *gspca_dev = 285 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 286 struct sd *sd = (struct sd *)gspca_dev; 287 288 gspca_dev->usb_err = 0; 289 290 if (!gspca_dev->streaming) 291 return 0; 292 293 switch (ctrl->id) { 294 /* standalone gain control */ 295 case V4L2_CID_GAIN: 296 set_gain(gspca_dev, ctrl->val); 297 break; 298 /* autogain */ 299 case V4L2_CID_AUTOGAIN: 300 set_gain(gspca_dev, sd->gain->val); 301 break; 302 } 303 return gspca_dev->usb_err; 304 } 305 306 static const struct v4l2_ctrl_ops sd_ctrl_ops = { 307 .s_ctrl = sd_s_ctrl, 308 }; 309 310 311 static int sd_init_controls(struct gspca_dev *gspca_dev) 312 { 313 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 314 struct sd *sd = (struct sd *)gspca_dev; 315 316 gspca_dev->vdev.ctrl_handler = hdl; 317 v4l2_ctrl_handler_init(hdl, 2); 318 319 switch (sd->model) { 320 case 0x7003: 321 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 322 V4L2_CID_GAIN, 0, 20, 1, 0); 323 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 324 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 325 break; 326 default: 327 break; 328 } 329 330 return 0; 331 } 332 static int start_spy_cam(struct gspca_dev *gspca_dev) 333 { 334 struct init_command spy_start_commands[] = { 335 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 336 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 337 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 338 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 339 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 340 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 341 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ 342 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ 343 /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ 344 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, 345 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ 346 /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ 347 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 348 /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ 349 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 350 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 351 /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ 352 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 353 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 354 /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ 355 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 356 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 357 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 358 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 359 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 360 {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, 361 {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ 362 /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 363 {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 364 /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ 365 {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 366 {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ 367 {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, 368 /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 369 {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, 370 {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, 371 {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, 372 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 373 {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, 374 {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, 375 {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, 376 /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ 377 /* brightness or gain. 0 is default. 4 is good 378 * indoors at night with incandescent lighting */ 379 {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, 380 {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ 381 {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, 382 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 383 {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, 384 {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, 385 /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ 386 {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ 387 /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ 388 {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, 389 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ 390 /* Camera should start to capture now. */ 391 }; 392 393 return run_start_commands(gspca_dev, spy_start_commands, 394 ARRAY_SIZE(spy_start_commands)); 395 } 396 397 static int start_cif_cam(struct gspca_dev *gspca_dev) 398 { 399 struct init_command cif_start_commands[] = { 400 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 401 /* The entire sequence below seems redundant */ 402 /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 403 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 404 {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, 405 {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, 406 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 407 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? 408 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? 409 {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 410 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 411 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 412 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 413 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 414 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 415 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 416 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 417 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 418 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 419 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 420 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ 421 {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, 422 {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, 423 {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, 424 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 425 {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, 426 {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, 427 {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, 428 {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, 429 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 430 {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, 431 {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, 432 {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, 433 {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, 434 {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, 435 {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, 436 {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, 437 {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, 438 {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, 439 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 440 {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, 441 {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, 442 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 443 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ 444 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ 445 /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 446 * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing 447 * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ 448 /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 449 * causes subsampling 450 * but not a change in the resolution setting! */ 451 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 452 {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, 453 {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, 454 {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, 455 {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 456 {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, 457 {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, 458 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 459 {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, 460 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 461 {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 462 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 463 {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, 464 {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 465 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 466 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ 467 /* Camera should start to capture now. */ 468 }; 469 470 return run_start_commands(gspca_dev, cif_start_commands, 471 ARRAY_SIZE(cif_start_commands)); 472 } 473 474 static int start_ms350_cam(struct gspca_dev *gspca_dev) 475 { 476 struct init_command ms350_start_commands[] = { 477 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 478 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 479 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 480 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 481 {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 482 {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 483 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 484 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 485 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 486 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 487 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, 488 {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 489 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 490 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 491 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 492 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 493 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 494 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 495 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 496 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 497 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 498 {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, 499 {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, 500 {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, 501 {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, 502 {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, 503 {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, 504 {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, 505 {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, 506 {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, 507 {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, 508 {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, 509 {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 510 {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, 511 {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, 512 {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, 513 {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, 514 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 515 {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, 516 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 517 {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, 518 {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, 519 {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, 520 {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, 521 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ 522 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ 523 {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ 524 {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 525 {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ 526 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 527 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 528 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 529 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 530 {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, 531 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 532 {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, 533 {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, 534 {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, 535 /* Camera should start to capture now. */ 536 }; 537 538 return run_start_commands(gspca_dev, ms350_start_commands, 539 ARRAY_SIZE(ms350_start_commands)); 540 } 541 542 static int start_genius_cam(struct gspca_dev *gspca_dev) 543 { 544 struct init_command genius_start_commands[] = { 545 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 546 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 547 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 548 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 549 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 550 /* "preliminary" width and height settings */ 551 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 552 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 553 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 554 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 555 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 556 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 557 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 558 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 559 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 560 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 561 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 562 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 563 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 564 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 565 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 566 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 567 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 568 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 569 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 570 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 571 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 572 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 573 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 574 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 575 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 576 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 577 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 578 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 579 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 580 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 581 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 582 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 583 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ 584 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ 585 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 586 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 587 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 588 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 589 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 590 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 591 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 592 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 593 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 594 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 595 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 596 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 597 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 598 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 599 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 600 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 601 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 602 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 603 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 604 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 605 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 606 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} 607 /* Camera should start to capture now. */ 608 }; 609 610 return run_start_commands(gspca_dev, genius_start_commands, 611 ARRAY_SIZE(genius_start_commands)); 612 } 613 614 static int start_genius_videocam_live(struct gspca_dev *gspca_dev) 615 { 616 int r; 617 struct sd *sd = (struct sd *) gspca_dev; 618 struct init_command genius_vcam_live_start_commands[] = { 619 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0}, 620 {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 621 {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 622 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 623 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 624 625 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 626 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 627 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 628 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 629 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 630 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 631 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 632 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 633 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 634 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 635 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 636 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 637 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 638 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 639 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 640 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 641 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 642 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 643 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 644 {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4}, 645 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 646 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 647 {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4}, 648 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 649 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 650 {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 651 {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 652 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 653 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 654 {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 655 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 656 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 657 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 658 {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 659 {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 660 {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 661 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 662 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 663 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 664 {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4}, 665 {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4}, 666 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 667 {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 668 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 669 {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 670 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 671 {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 672 {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 673 {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 674 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 675 {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 676 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 677 {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 678 {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 679 {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 680 {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 681 {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 682 {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 683 {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 684 {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 685 {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 686 {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 687 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 688 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 689 {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 690 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 691 {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 692 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 693 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 694 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 695 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 696 {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 697 {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 698 {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 699 {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 700 {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 701 {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 702 {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 703 {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 704 {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 705 {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 706 {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 707 {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 708 {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 709 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}, 710 /* Camera should start to capture now. */ 711 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0}, 712 {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0}, 713 {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0}, 714 }; 715 716 r = run_start_commands(gspca_dev, genius_vcam_live_start_commands, 717 ARRAY_SIZE(genius_vcam_live_start_commands)); 718 if (r < 0) 719 return r; 720 721 if (sd->gain) 722 set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); 723 724 return r; 725 } 726 727 static int start_vivitar_cam(struct gspca_dev *gspca_dev) 728 { 729 struct init_command vivitar_start_commands[] = { 730 {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 731 {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 732 {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 733 {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, 734 {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 735 {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 736 {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 737 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 738 {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 739 {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, 740 /* 741 * Above is changed from OEM 0x0b. Fixes Bayer tiling. 742 * Presumably gives a vertical shift of one row. 743 */ 744 {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 745 /* Above seems to do horizontal shift. */ 746 {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 747 {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 748 {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 749 {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 750 {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 751 {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 752 /* Above three commands seem to relate to brightness. */ 753 {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 754 {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 755 {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 756 {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, 757 {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, 758 {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, 759 {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, 760 {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 761 {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, 762 {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, 763 {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, 764 {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, 765 {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, 766 {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, 767 {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, 768 {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, 769 {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 770 {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, 771 {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, 772 {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, 773 {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, 774 {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, 775 {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, 776 {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, 777 {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, 778 {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, 779 {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, 780 {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, 781 {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, 782 {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, 783 {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, 784 {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, 785 {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, 786 {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, 787 {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, 788 {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, 789 {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, 790 /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 791 {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 792 {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ 793 {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 794 {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, 795 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 796 {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, 797 {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 798 {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, 799 /* Above is brightness; OEM driver setting is 0x10 */ 800 {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 801 {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 802 {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} 803 }; 804 805 return run_start_commands(gspca_dev, vivitar_start_commands, 806 ARRAY_SIZE(vivitar_start_commands)); 807 } 808 809 static int sd_start(struct gspca_dev *gspca_dev) 810 { 811 struct sd *sd = (struct sd *) gspca_dev; 812 int err_code; 813 814 sd->sof_read = 0; 815 816 switch (sd->model) { 817 case 0x7005: 818 err_code = start_genius_cam(gspca_dev); 819 break; 820 case 0x7003: 821 err_code = start_genius_videocam_live(gspca_dev); 822 break; 823 case 0x8001: 824 err_code = start_spy_cam(gspca_dev); 825 break; 826 case 0x8003: 827 err_code = start_cif_cam(gspca_dev); 828 break; 829 case 0x8008: 830 err_code = start_ms350_cam(gspca_dev); 831 break; 832 case 0x800a: 833 err_code = start_vivitar_cam(gspca_dev); 834 break; 835 default: 836 pr_err("Starting unknown camera, please report this\n"); 837 return -ENXIO; 838 } 839 840 sd->avg_lum = -1; 841 842 return err_code; 843 } 844 845 static void sd_stopN(struct gspca_dev *gspca_dev) 846 { 847 int result; 848 __u8 data[6]; 849 850 result = sn9c2028_read1(gspca_dev); 851 if (result < 0) 852 PERR("Camera Stop read failed"); 853 854 memset(data, 0, 6); 855 data[0] = 0x14; 856 result = sn9c2028_command(gspca_dev, data); 857 if (result < 0) 858 PERR("Camera Stop command failed"); 859 } 860 861 static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum) 862 { 863 struct sd *sd = (struct sd *) gspca_dev; 864 s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); 865 866 if (avg_lum == -1) 867 return; 868 869 if (avg_lum < MIN_AVG_LUM) { 870 if (cur_gain == sd->gain->maximum) 871 return; 872 cur_gain++; 873 v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 874 } 875 if (avg_lum > MAX_AVG_LUM) { 876 if (cur_gain == sd->gain->minimum) 877 return; 878 cur_gain--; 879 v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 880 } 881 882 } 883 884 static void sd_dqcallback(struct gspca_dev *gspca_dev) 885 { 886 struct sd *sd = (struct sd *) gspca_dev; 887 888 if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) 889 return; 890 891 do_autogain(gspca_dev, sd->avg_lum); 892 } 893 894 /* Include sn9c2028 sof detection functions */ 895 #include "sn9c2028.h" 896 897 static void sd_pkt_scan(struct gspca_dev *gspca_dev, 898 __u8 *data, /* isoc packet */ 899 int len) /* iso packet length */ 900 { 901 unsigned char *sof; 902 903 sof = sn9c2028_find_sof(gspca_dev, data, len); 904 if (sof) { 905 int n; 906 907 /* finish decoding current frame */ 908 n = sof - data; 909 if (n > sizeof sn9c2028_sof_marker) 910 n -= sizeof sn9c2028_sof_marker; 911 else 912 n = 0; 913 gspca_frame_add(gspca_dev, LAST_PACKET, data, n); 914 /* Start next frame. */ 915 gspca_frame_add(gspca_dev, FIRST_PACKET, 916 sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); 917 len -= sof - data; 918 data = sof; 919 } 920 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 921 } 922 923 /* sub-driver description */ 924 static const struct sd_desc sd_desc = { 925 .name = MODULE_NAME, 926 .config = sd_config, 927 .init = sd_init, 928 .init_controls = sd_init_controls, 929 .start = sd_start, 930 .stopN = sd_stopN, 931 .dq_callback = sd_dqcallback, 932 .pkt_scan = sd_pkt_scan, 933 }; 934 935 /* -- module initialisation -- */ 936 static const struct usb_device_id device_table[] = { 937 {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ 938 {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2 */ 939 /* The Genius Smart is untested. I can't find an owner ! */ 940 /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ 941 {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ 942 {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ 943 /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ 944 {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ 945 {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ 946 {} 947 }; 948 MODULE_DEVICE_TABLE(usb, device_table); 949 950 /* -- device connect -- */ 951 static int sd_probe(struct usb_interface *intf, 952 const struct usb_device_id *id) 953 { 954 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 955 THIS_MODULE); 956 } 957 958 static struct usb_driver sd_driver = { 959 .name = MODULE_NAME, 960 .id_table = device_table, 961 .probe = sd_probe, 962 .disconnect = gspca_disconnect, 963 #ifdef CONFIG_PM 964 .suspend = gspca_suspend, 965 .resume = gspca_resume, 966 .reset_resume = gspca_resume, 967 #endif 968 }; 969 970 module_usb_driver(sd_driver); 971