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