pac7311.c (19356B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Pixart PAC7311 library 4 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li 5 * 6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 7 */ 8 9/* Some documentation about various registers as determined by trial and error. 10 * 11 * Register page 1: 12 * 13 * Address Description 14 * 0x08 Unknown compressor related, must always be 8 except when not 15 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! 16 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted) 17 * bits 345 seem to toggle per color gains on/off (inverted) 18 * 0x78 Global control, bit 6 controls the LED (inverted) 19 * 0x80 Compression balance, interesting settings: 20 * 0x01 Use this to allow the camera to switch to higher compr. 21 * on the fly. Needed to stay within bandwidth @ 640x480@30 22 * 0x1c From usb captures under Windows for 640x480 23 * 0x2a Values >= this switch the camera to a lower compression, 24 * using the same table for both luminance and chrominance. 25 * This gives a sharper picture. Usable only at 640x480@ < 26 * 15 fps or 320x240 / 160x120. Note currently the driver 27 * does not use this as the quality gain is small and the 28 * generated JPG-s are only understood by v4l-utils >= 0.8.9 29 * 0x3f From usb captures under Windows for 320x240 30 * 0x69 From usb captures under Windows for 160x120 31 * 32 * Register page 4: 33 * 34 * Address Description 35 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on 36 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? 37 * 0x0f Master gain 1-245, low value = high gain 38 * 0x10 Another gain 0-15, limited influence (1-2x gain I guess) 39 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused 40 * Note setting vflip disabled leads to a much lower image quality, 41 * so we always vflip, and tell userspace to flip it back 42 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to 43 * completely disable the analog amplification block. Set to 0x68 44 * for max gain, 0x14 for minimal gain. 45 */ 46 47#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 48 49#define MODULE_NAME "pac7311" 50 51#include <linux/input.h> 52#include "gspca.h" 53/* Include pac common sof detection functions */ 54#include "pac_common.h" 55 56#define PAC7311_GAIN_DEFAULT 122 57#define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */ 58 59MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); 60MODULE_DESCRIPTION("Pixart PAC7311"); 61MODULE_LICENSE("GPL"); 62 63struct sd { 64 struct gspca_dev gspca_dev; /* !! must be the first item */ 65 66 struct v4l2_ctrl *contrast; 67 struct v4l2_ctrl *hflip; 68 69 u8 sof_read; 70 u8 autogain_ignore_frames; 71 72 atomic_t avg_lum; 73}; 74 75static const struct v4l2_pix_format vga_mode[] = { 76 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, 77 .bytesperline = 160, 78 .sizeimage = 160 * 120 * 3 / 8 + 590, 79 .colorspace = V4L2_COLORSPACE_JPEG, 80 .priv = 2}, 81 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, 82 .bytesperline = 320, 83 .sizeimage = 320 * 240 * 3 / 8 + 590, 84 .colorspace = V4L2_COLORSPACE_JPEG, 85 .priv = 1}, 86 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, 87 .bytesperline = 640, 88 .sizeimage = 640 * 480 * 3 / 8 + 590, 89 .colorspace = V4L2_COLORSPACE_JPEG, 90 .priv = 0}, 91}; 92 93#define LOAD_PAGE4 254 94#define END_OF_SEQUENCE 0 95 96static const __u8 init_7311[] = { 97 0xff, 0x01, 98 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ 99 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ 100 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */ 101 0xff, 0x04, 102 0x27, 0x80, 103 0x28, 0xca, 104 0x29, 0x53, 105 0x2a, 0x0e, 106 0xff, 0x01, 107 0x3e, 0x20, 108}; 109 110static const __u8 start_7311[] = { 111/* index, len, [value]* */ 112 0xff, 1, 0x01, /* page 1 */ 113 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, 114 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, 115 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, 116 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 118 0x00, 0x00, 0x00, 119 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, 120 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, 121 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, 122 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, 123 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b, 124 0xd0, 0xff, 125 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80, 126 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84, 127 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14, 128 0x18, 0x20, 129 0x96, 3, 0x01, 0x08, 0x04, 130 0xa0, 4, 0x44, 0x44, 0x44, 0x04, 131 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, 132 0x3f, 0x00, 0x0a, 0x01, 0x00, 133 0xff, 1, 0x04, /* page 4 */ 134 0, LOAD_PAGE4, /* load the page 4 */ 135 0x11, 1, 0x01, 136 0, END_OF_SEQUENCE /* end of sequence */ 137}; 138 139#define SKIP 0xaa 140/* page 4 - the value SKIP says skip the index - see reg_w_page() */ 141static const __u8 page4_7311[] = { 142 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, 143 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62, 144 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 145 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP, 146 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68, 147 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, 148 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 149}; 150 151static void reg_w_buf(struct gspca_dev *gspca_dev, 152 __u8 index, 153 const u8 *buffer, int len) 154{ 155 int ret; 156 157 if (gspca_dev->usb_err < 0) 158 return; 159 memcpy(gspca_dev->usb_buf, buffer, len); 160 ret = usb_control_msg(gspca_dev->dev, 161 usb_sndctrlpipe(gspca_dev->dev, 0), 162 0, /* request */ 163 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 164 0, /* value */ 165 index, gspca_dev->usb_buf, len, 166 500); 167 if (ret < 0) { 168 pr_err("reg_w_buf() failed index 0x%02x, error %d\n", 169 index, ret); 170 gspca_dev->usb_err = ret; 171 } 172} 173 174 175static void reg_w(struct gspca_dev *gspca_dev, 176 __u8 index, 177 __u8 value) 178{ 179 int ret; 180 181 if (gspca_dev->usb_err < 0) 182 return; 183 gspca_dev->usb_buf[0] = value; 184 ret = usb_control_msg(gspca_dev->dev, 185 usb_sndctrlpipe(gspca_dev->dev, 0), 186 0, /* request */ 187 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 188 0, index, gspca_dev->usb_buf, 1, 189 500); 190 if (ret < 0) { 191 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", 192 index, value, ret); 193 gspca_dev->usb_err = ret; 194 } 195} 196 197static void reg_w_seq(struct gspca_dev *gspca_dev, 198 const __u8 *seq, int len) 199{ 200 while (--len >= 0) { 201 reg_w(gspca_dev, seq[0], seq[1]); 202 seq += 2; 203 } 204} 205 206/* load the beginning of a page */ 207static void reg_w_page(struct gspca_dev *gspca_dev, 208 const __u8 *page, int len) 209{ 210 int index; 211 int ret = 0; 212 213 if (gspca_dev->usb_err < 0) 214 return; 215 for (index = 0; index < len; index++) { 216 if (page[index] == SKIP) /* skip this index */ 217 continue; 218 gspca_dev->usb_buf[0] = page[index]; 219 ret = usb_control_msg(gspca_dev->dev, 220 usb_sndctrlpipe(gspca_dev->dev, 0), 221 0, /* request */ 222 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 223 0, index, gspca_dev->usb_buf, 1, 224 500); 225 if (ret < 0) { 226 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", 227 index, page[index], ret); 228 gspca_dev->usb_err = ret; 229 break; 230 } 231 } 232} 233 234/* output a variable sequence */ 235static void reg_w_var(struct gspca_dev *gspca_dev, 236 const __u8 *seq, 237 const __u8 *page4, unsigned int page4_len) 238{ 239 int index, len; 240 241 for (;;) { 242 index = *seq++; 243 len = *seq++; 244 switch (len) { 245 case END_OF_SEQUENCE: 246 return; 247 case LOAD_PAGE4: 248 reg_w_page(gspca_dev, page4, page4_len); 249 break; 250 default: 251 if (len > USB_BUF_SZ) { 252 gspca_err(gspca_dev, "Incorrect variable sequence\n"); 253 return; 254 } 255 while (len > 0) { 256 if (len < 8) { 257 reg_w_buf(gspca_dev, 258 index, seq, len); 259 seq += len; 260 break; 261 } 262 reg_w_buf(gspca_dev, index, seq, 8); 263 seq += 8; 264 index += 8; 265 len -= 8; 266 } 267 } 268 } 269 /* not reached */ 270} 271 272/* this function is called at probe time for pac7311 */ 273static int sd_config(struct gspca_dev *gspca_dev, 274 const struct usb_device_id *id) 275{ 276 struct cam *cam = &gspca_dev->cam; 277 278 cam->cam_mode = vga_mode; 279 cam->nmodes = ARRAY_SIZE(vga_mode); 280 cam->input_flags = V4L2_IN_ST_VFLIP; 281 282 return 0; 283} 284 285static void setcontrast(struct gspca_dev *gspca_dev, s32 val) 286{ 287 reg_w(gspca_dev, 0xff, 0x04); 288 reg_w(gspca_dev, 0x10, val); 289 /* load registers to sensor (Bit 0, auto clear) */ 290 reg_w(gspca_dev, 0x11, 0x01); 291} 292 293static void setgain(struct gspca_dev *gspca_dev, s32 val) 294{ 295 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ 296 reg_w(gspca_dev, 0x0e, 0x00); 297 reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1); 298 299 /* load registers to sensor (Bit 0, auto clear) */ 300 reg_w(gspca_dev, 0x11, 0x01); 301} 302 303static void setexposure(struct gspca_dev *gspca_dev, s32 val) 304{ 305 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ 306 reg_w(gspca_dev, 0x02, val); 307 308 /* load registers to sensor (Bit 0, auto clear) */ 309 reg_w(gspca_dev, 0x11, 0x01); 310 311 /* 312 * Page 1 register 8 must always be 0x08 except when not in 313 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9 314 */ 315 reg_w(gspca_dev, 0xff, 0x01); 316 if (gspca_dev->pixfmt.width != 640 && val <= 3) 317 reg_w(gspca_dev, 0x08, 0x09); 318 else 319 reg_w(gspca_dev, 0x08, 0x08); 320 321 /* 322 * Page1 register 80 sets the compression balance, normally we 323 * want / use 0x1c, but for 640x480@30fps we must allow the 324 * camera to use higher compression or we may run out of 325 * bandwidth. 326 */ 327 if (gspca_dev->pixfmt.width == 640 && val == 2) 328 reg_w(gspca_dev, 0x80, 0x01); 329 else 330 reg_w(gspca_dev, 0x80, 0x1c); 331 332 /* load registers to sensor (Bit 0, auto clear) */ 333 reg_w(gspca_dev, 0x11, 0x01); 334} 335 336static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip) 337{ 338 __u8 data; 339 340 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ 341 data = (hflip ? 0x04 : 0x00) | 342 (vflip ? 0x08 : 0x00); 343 reg_w(gspca_dev, 0x21, data); 344 345 /* load registers to sensor (Bit 0, auto clear) */ 346 reg_w(gspca_dev, 0x11, 0x01); 347} 348 349/* this function is called at probe and resume time for pac7311 */ 350static int sd_init(struct gspca_dev *gspca_dev) 351{ 352 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); 353 return gspca_dev->usb_err; 354} 355 356static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 357{ 358 struct gspca_dev *gspca_dev = 359 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 360 struct sd *sd = (struct sd *)gspca_dev; 361 362 gspca_dev->usb_err = 0; 363 364 if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { 365 /* when switching to autogain set defaults to make sure 366 we are on a valid point of the autogain gain / 367 exposure knee graph, and give this change time to 368 take effect before doing autogain. */ 369 gspca_dev->exposure->val = PAC7311_EXPOSURE_DEFAULT; 370 gspca_dev->gain->val = PAC7311_GAIN_DEFAULT; 371 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; 372 } 373 374 if (!gspca_dev->streaming) 375 return 0; 376 377 switch (ctrl->id) { 378 case V4L2_CID_CONTRAST: 379 setcontrast(gspca_dev, ctrl->val); 380 break; 381 case V4L2_CID_AUTOGAIN: 382 if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) 383 setexposure(gspca_dev, gspca_dev->exposure->val); 384 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) 385 setgain(gspca_dev, gspca_dev->gain->val); 386 break; 387 case V4L2_CID_HFLIP: 388 sethvflip(gspca_dev, sd->hflip->val, 1); 389 break; 390 default: 391 return -EINVAL; 392 } 393 return gspca_dev->usb_err; 394} 395 396static const struct v4l2_ctrl_ops sd_ctrl_ops = { 397 .s_ctrl = sd_s_ctrl, 398}; 399 400/* this function is called at probe time */ 401static int sd_init_controls(struct gspca_dev *gspca_dev) 402{ 403 struct sd *sd = (struct sd *) gspca_dev; 404 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 405 406 gspca_dev->vdev.ctrl_handler = hdl; 407 v4l2_ctrl_handler_init(hdl, 5); 408 409 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 410 V4L2_CID_CONTRAST, 0, 15, 1, 7); 411 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 412 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 413 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 414 V4L2_CID_EXPOSURE, 2, 63, 1, 415 PAC7311_EXPOSURE_DEFAULT); 416 gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 417 V4L2_CID_GAIN, 0, 244, 1, 418 PAC7311_GAIN_DEFAULT); 419 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 420 V4L2_CID_HFLIP, 0, 1, 1, 0); 421 422 if (hdl->error) { 423 pr_err("Could not initialize controls\n"); 424 return hdl->error; 425 } 426 427 v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); 428 return 0; 429} 430 431/* -- start the camera -- */ 432static int sd_start(struct gspca_dev *gspca_dev) 433{ 434 struct sd *sd = (struct sd *) gspca_dev; 435 436 sd->sof_read = 0; 437 438 reg_w_var(gspca_dev, start_7311, 439 page4_7311, sizeof(page4_7311)); 440 setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast)); 441 setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain)); 442 setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure)); 443 sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1); 444 445 /* set correct resolution */ 446 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 447 case 2: /* 160x120 */ 448 reg_w(gspca_dev, 0xff, 0x01); 449 reg_w(gspca_dev, 0x17, 0x20); 450 reg_w(gspca_dev, 0x87, 0x10); 451 break; 452 case 1: /* 320x240 */ 453 reg_w(gspca_dev, 0xff, 0x01); 454 reg_w(gspca_dev, 0x17, 0x30); 455 reg_w(gspca_dev, 0x87, 0x11); 456 break; 457 case 0: /* 640x480 */ 458 reg_w(gspca_dev, 0xff, 0x01); 459 reg_w(gspca_dev, 0x17, 0x00); 460 reg_w(gspca_dev, 0x87, 0x12); 461 break; 462 } 463 464 sd->sof_read = 0; 465 sd->autogain_ignore_frames = 0; 466 atomic_set(&sd->avg_lum, -1); 467 468 /* start stream */ 469 reg_w(gspca_dev, 0xff, 0x01); 470 reg_w(gspca_dev, 0x78, 0x05); 471 472 return gspca_dev->usb_err; 473} 474 475static void sd_stopN(struct gspca_dev *gspca_dev) 476{ 477 reg_w(gspca_dev, 0xff, 0x04); 478 reg_w(gspca_dev, 0x27, 0x80); 479 reg_w(gspca_dev, 0x28, 0xca); 480 reg_w(gspca_dev, 0x29, 0x53); 481 reg_w(gspca_dev, 0x2a, 0x0e); 482 reg_w(gspca_dev, 0xff, 0x01); 483 reg_w(gspca_dev, 0x3e, 0x20); 484 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ 485 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ 486 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ 487} 488 489static void do_autogain(struct gspca_dev *gspca_dev) 490{ 491 struct sd *sd = (struct sd *) gspca_dev; 492 int avg_lum = atomic_read(&sd->avg_lum); 493 int desired_lum, deadzone; 494 495 if (avg_lum == -1) 496 return; 497 498 desired_lum = 170; 499 deadzone = 20; 500 501 if (sd->autogain_ignore_frames > 0) 502 sd->autogain_ignore_frames--; 503 else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, 504 desired_lum, deadzone)) 505 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; 506} 507 508/* JPEG header, part 1 */ 509static const unsigned char pac_jpeg_header1[] = { 510 0xff, 0xd8, /* SOI: Start of Image */ 511 512 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ 513 0x00, 0x11, /* length = 17 bytes (including this length field) */ 514 0x08 /* Precision: 8 */ 515 /* 2 bytes is placed here: number of image lines */ 516 /* 2 bytes is placed here: samples per line */ 517}; 518 519/* JPEG header, continued */ 520static const unsigned char pac_jpeg_header2[] = { 521 0x03, /* Number of image components: 3 */ 522 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ 523 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ 524 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ 525 526 0xff, 0xda, /* SOS: Start Of Scan */ 527 0x00, 0x0c, /* length = 12 bytes (including this length field) */ 528 0x03, /* number of components: 3 */ 529 0x01, 0x00, /* selector 1, table 0x00 */ 530 0x02, 0x11, /* selector 2, table 0x11 */ 531 0x03, 0x11, /* selector 3, table 0x11 */ 532 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ 533 0x00 /* Successive approximation: 0 */ 534}; 535 536static void pac_start_frame(struct gspca_dev *gspca_dev, 537 __u16 lines, __u16 samples_per_line) 538{ 539 unsigned char tmpbuf[4]; 540 541 gspca_frame_add(gspca_dev, FIRST_PACKET, 542 pac_jpeg_header1, sizeof(pac_jpeg_header1)); 543 544 tmpbuf[0] = lines >> 8; 545 tmpbuf[1] = lines & 0xff; 546 tmpbuf[2] = samples_per_line >> 8; 547 tmpbuf[3] = samples_per_line & 0xff; 548 549 gspca_frame_add(gspca_dev, INTER_PACKET, 550 tmpbuf, sizeof(tmpbuf)); 551 gspca_frame_add(gspca_dev, INTER_PACKET, 552 pac_jpeg_header2, sizeof(pac_jpeg_header2)); 553} 554 555/* this function is run at interrupt level */ 556static void sd_pkt_scan(struct gspca_dev *gspca_dev, 557 u8 *data, /* isoc packet */ 558 int len) /* iso packet length */ 559{ 560 struct sd *sd = (struct sd *) gspca_dev; 561 u8 *image; 562 unsigned char *sof; 563 564 sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len); 565 if (sof) { 566 int n, lum_offset, footer_length; 567 568 /* 569 * 6 bytes after the FF D9 EOF marker a number of lumination 570 * bytes are send corresponding to different parts of the 571 * image, the 14th and 15th byte after the EOF seem to 572 * correspond to the center of the image. 573 */ 574 lum_offset = 24 + sizeof pac_sof_marker; 575 footer_length = 26; 576 577 /* Finish decoding current frame */ 578 n = (sof - data) - (footer_length + sizeof pac_sof_marker); 579 if (n < 0) { 580 gspca_dev->image_len += n; 581 n = 0; 582 } else { 583 gspca_frame_add(gspca_dev, INTER_PACKET, data, n); 584 } 585 image = gspca_dev->image; 586 if (image != NULL 587 && image[gspca_dev->image_len - 2] == 0xff 588 && image[gspca_dev->image_len - 1] == 0xd9) 589 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 590 591 n = sof - data; 592 len -= n; 593 data = sof; 594 595 /* Get average lumination */ 596 if (gspca_dev->last_packet_type == LAST_PACKET && 597 n >= lum_offset) 598 atomic_set(&sd->avg_lum, data[-lum_offset] + 599 data[-lum_offset + 1]); 600 else 601 atomic_set(&sd->avg_lum, -1); 602 603 /* Start the new frame with the jpeg header */ 604 pac_start_frame(gspca_dev, 605 gspca_dev->pixfmt.height, gspca_dev->pixfmt.width); 606 } 607 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 608} 609 610#if IS_ENABLED(CONFIG_INPUT) 611static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, 612 u8 *data, /* interrupt packet data */ 613 int len) /* interrupt packet length */ 614{ 615 int ret = -EINVAL; 616 u8 data0, data1; 617 618 if (len == 2) { 619 data0 = data[0]; 620 data1 = data[1]; 621 if ((data0 == 0x00 && data1 == 0x11) || 622 (data0 == 0x22 && data1 == 0x33) || 623 (data0 == 0x44 && data1 == 0x55) || 624 (data0 == 0x66 && data1 == 0x77) || 625 (data0 == 0x88 && data1 == 0x99) || 626 (data0 == 0xaa && data1 == 0xbb) || 627 (data0 == 0xcc && data1 == 0xdd) || 628 (data0 == 0xee && data1 == 0xff)) { 629 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); 630 input_sync(gspca_dev->input_dev); 631 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 632 input_sync(gspca_dev->input_dev); 633 ret = 0; 634 } 635 } 636 637 return ret; 638} 639#endif 640 641static const struct sd_desc sd_desc = { 642 .name = MODULE_NAME, 643 .config = sd_config, 644 .init = sd_init, 645 .init_controls = sd_init_controls, 646 .start = sd_start, 647 .stopN = sd_stopN, 648 .pkt_scan = sd_pkt_scan, 649 .dq_callback = do_autogain, 650#if IS_ENABLED(CONFIG_INPUT) 651 .int_pkt_scan = sd_int_pkt_scan, 652#endif 653}; 654 655/* -- module initialisation -- */ 656static const struct usb_device_id device_table[] = { 657 {USB_DEVICE(0x093a, 0x2600)}, 658 {USB_DEVICE(0x093a, 0x2601)}, 659 {USB_DEVICE(0x093a, 0x2603)}, 660 {USB_DEVICE(0x093a, 0x2608)}, 661 {USB_DEVICE(0x093a, 0x260e)}, 662 {USB_DEVICE(0x093a, 0x260f)}, 663 {} 664}; 665MODULE_DEVICE_TABLE(usb, device_table); 666 667/* -- device connect -- */ 668static int sd_probe(struct usb_interface *intf, 669 const struct usb_device_id *id) 670{ 671 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 672 THIS_MODULE); 673} 674 675static struct usb_driver sd_driver = { 676 .name = MODULE_NAME, 677 .id_table = device_table, 678 .probe = sd_probe, 679 .disconnect = gspca_disconnect, 680#ifdef CONFIG_PM 681 .suspend = gspca_suspend, 682 .resume = gspca_resume, 683 .reset_resume = gspca_resume, 684#endif 685}; 686 687module_usb_driver(sd_driver);