2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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
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.
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
22 /* Some documentation about various registers as determined by trial and error.
27 * 0x08 Unknown compressor related, must always be 8 except when not
28 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
29 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
30 * bits 345 seem to toggle per color gains on/off (inverted)
31 * 0x78 Global control, bit 6 controls the LED (inverted)
32 * 0x80 Compression balance, interesting settings:
33 * 0x01 Use this to allow the camera to switch to higher compr.
34 * on the fly. Needed to stay within bandwidth @ 640x480@30
35 * 0x1c From usb captures under Windows for 640x480
36 * 0x2a Values >= this switch the camera to a lower compression,
37 * using the same table for both luminance and chrominance.
38 * This gives a sharper picture. Usable only at 640x480@ <
39 * 15 fps or 320x240 / 160x120. Note currently the driver
40 * does not use this as the quality gain is small and the
41 * generated JPG-s are only understood by v4l-utils >= 0.8.9
42 * 0x3f From usb captures under Windows for 320x240
43 * 0x69 From usb captures under Windows for 160x120
48 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
49 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
50 * 0x0f Master gain 1-245, low value = high gain
51 * 0x10 Another gain 0-15, limited influence (1-2x gain I guess)
52 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
53 * Note setting vflip disabled leads to a much lower image quality,
54 * so we always vflip, and tell userspace to flip it back
55 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
56 * completely disable the analog amplification block. Set to 0x68
57 * for max gain, 0x14 for minimal gain.
60 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
62 #define MODULE_NAME "pac7311"
64 #include <linux/input.h>
66 /* Include pac common sof detection functions */
67 #include "pac_common.h"
69 #define PAC7311_GAIN_DEFAULT 122
70 #define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */
72 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73 MODULE_DESCRIPTION("Pixart PAC7311");
74 MODULE_LICENSE("GPL");
77 struct gspca_dev gspca_dev
; /* !! must be the first item */
79 struct v4l2_ctrl
*contrast
;
80 struct v4l2_ctrl
*hflip
;
83 u8 autogain_ignore_frames
;
88 static const struct v4l2_pix_format vga_mode
[] = {
89 {160, 120, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
91 .sizeimage
= 160 * 120 * 3 / 8 + 590,
92 .colorspace
= V4L2_COLORSPACE_JPEG
,
94 {320, 240, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
96 .sizeimage
= 320 * 240 * 3 / 8 + 590,
97 .colorspace
= V4L2_COLORSPACE_JPEG
,
99 {640, 480, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
101 .sizeimage
= 640 * 480 * 3 / 8 + 590,
102 .colorspace
= V4L2_COLORSPACE_JPEG
,
106 #define LOAD_PAGE4 254
107 #define END_OF_SEQUENCE 0
109 static const __u8 init_7311
[] = {
111 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
112 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
113 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
123 static const __u8 start_7311
[] = {
124 /* index, len, [value]* */
125 0xff, 1, 0x01, /* page 1 */
126 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
127 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
128 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
129 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
133 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
134 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
135 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
136 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
138 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
139 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
140 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
142 0x96, 3, 0x01, 0x08, 0x04,
143 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
144 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
145 0x3f, 0x00, 0x0a, 0x01, 0x00,
146 0xff, 1, 0x04, /* page 4 */
147 0, LOAD_PAGE4
, /* load the page 4 */
149 0, END_OF_SEQUENCE
/* end of sequence */
153 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
154 static const __u8 page4_7311
[] = {
155 SKIP
, SKIP
, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
156 0x09, 0x00, SKIP
, SKIP
, 0x07, 0x00, 0x00, 0x62,
157 0x08, SKIP
, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP
,
159 SKIP
, 0x00, 0x08, SKIP
, 0x03, SKIP
, 0x00, 0x68,
160 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
161 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
164 static void reg_w_buf(struct gspca_dev
*gspca_dev
,
166 const u8
*buffer
, int len
)
170 if (gspca_dev
->usb_err
< 0)
172 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
173 ret
= usb_control_msg(gspca_dev
->dev
,
174 usb_sndctrlpipe(gspca_dev
->dev
, 0),
176 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
178 index
, gspca_dev
->usb_buf
, len
,
181 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
183 gspca_dev
->usb_err
= ret
;
188 static void reg_w(struct gspca_dev
*gspca_dev
,
194 if (gspca_dev
->usb_err
< 0)
196 gspca_dev
->usb_buf
[0] = value
;
197 ret
= usb_control_msg(gspca_dev
->dev
,
198 usb_sndctrlpipe(gspca_dev
->dev
, 0),
200 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
201 0, index
, gspca_dev
->usb_buf
, 1,
204 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
206 gspca_dev
->usb_err
= ret
;
210 static void reg_w_seq(struct gspca_dev
*gspca_dev
,
211 const __u8
*seq
, int len
)
214 reg_w(gspca_dev
, seq
[0], seq
[1]);
219 /* load the beginning of a page */
220 static void reg_w_page(struct gspca_dev
*gspca_dev
,
221 const __u8
*page
, int len
)
226 if (gspca_dev
->usb_err
< 0)
228 for (index
= 0; index
< len
; index
++) {
229 if (page
[index
] == SKIP
) /* skip this index */
231 gspca_dev
->usb_buf
[0] = page
[index
];
232 ret
= usb_control_msg(gspca_dev
->dev
,
233 usb_sndctrlpipe(gspca_dev
->dev
, 0),
235 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
236 0, index
, gspca_dev
->usb_buf
, 1,
239 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
240 index
, page
[index
], ret
);
241 gspca_dev
->usb_err
= ret
;
247 /* output a variable sequence */
248 static void reg_w_var(struct gspca_dev
*gspca_dev
,
250 const __u8
*page4
, unsigned int page4_len
)
258 case END_OF_SEQUENCE
:
261 reg_w_page(gspca_dev
, page4
, page4_len
);
264 if (len
> USB_BUF_SZ
) {
265 PERR("Incorrect variable sequence");
275 reg_w_buf(gspca_dev
, index
, seq
, 8);
285 /* this function is called at probe time for pac7311 */
286 static int sd_config(struct gspca_dev
*gspca_dev
,
287 const struct usb_device_id
*id
)
289 struct cam
*cam
= &gspca_dev
->cam
;
291 cam
->cam_mode
= vga_mode
;
292 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
293 cam
->input_flags
= V4L2_IN_ST_VFLIP
;
298 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
300 reg_w(gspca_dev
, 0xff, 0x04);
301 reg_w(gspca_dev
, 0x10, val
);
302 /* load registers to sensor (Bit 0, auto clear) */
303 reg_w(gspca_dev
, 0x11, 0x01);
306 static void setgain(struct gspca_dev
*gspca_dev
, s32 val
)
308 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
309 reg_w(gspca_dev
, 0x0e, 0x00);
310 reg_w(gspca_dev
, 0x0f, gspca_dev
->gain
->maximum
- val
+ 1);
312 /* load registers to sensor (Bit 0, auto clear) */
313 reg_w(gspca_dev
, 0x11, 0x01);
316 static void setexposure(struct gspca_dev
*gspca_dev
, s32 val
)
318 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
319 reg_w(gspca_dev
, 0x02, val
);
321 /* load registers to sensor (Bit 0, auto clear) */
322 reg_w(gspca_dev
, 0x11, 0x01);
325 * Page 1 register 8 must always be 0x08 except when not in
326 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9
328 reg_w(gspca_dev
, 0xff, 0x01);
329 if (gspca_dev
->width
!= 640 && val
<= 3)
330 reg_w(gspca_dev
, 0x08, 0x09);
332 reg_w(gspca_dev
, 0x08, 0x08);
335 * Page1 register 80 sets the compression balance, normally we
336 * want / use 0x1c, but for 640x480@30fps we must allow the
337 * camera to use higher compression or we may run out of
340 if (gspca_dev
->width
== 640 && val
== 2)
341 reg_w(gspca_dev
, 0x80, 0x01);
343 reg_w(gspca_dev
, 0x80, 0x1c);
345 /* load registers to sensor (Bit 0, auto clear) */
346 reg_w(gspca_dev
, 0x11, 0x01);
349 static void sethvflip(struct gspca_dev
*gspca_dev
, s32 hflip
, s32 vflip
)
353 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
354 data
= (hflip
? 0x04 : 0x00) |
355 (vflip
? 0x08 : 0x00);
356 reg_w(gspca_dev
, 0x21, data
);
358 /* load registers to sensor (Bit 0, auto clear) */
359 reg_w(gspca_dev
, 0x11, 0x01);
362 /* this function is called at probe and resume time for pac7311 */
363 static int sd_init(struct gspca_dev
*gspca_dev
)
365 reg_w_seq(gspca_dev
, init_7311
, sizeof(init_7311
)/2);
366 return gspca_dev
->usb_err
;
369 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
371 struct gspca_dev
*gspca_dev
=
372 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
373 struct sd
*sd
= (struct sd
*)gspca_dev
;
375 gspca_dev
->usb_err
= 0;
377 if (ctrl
->id
== V4L2_CID_AUTOGAIN
&& ctrl
->is_new
&& ctrl
->val
) {
378 /* when switching to autogain set defaults to make sure
379 we are on a valid point of the autogain gain /
380 exposure knee graph, and give this change time to
381 take effect before doing autogain. */
382 gspca_dev
->exposure
->val
= PAC7311_EXPOSURE_DEFAULT
;
383 gspca_dev
->gain
->val
= PAC7311_GAIN_DEFAULT
;
384 sd
->autogain_ignore_frames
= PAC_AUTOGAIN_IGNORE_FRAMES
;
387 if (!gspca_dev
->streaming
)
391 case V4L2_CID_CONTRAST
:
392 setcontrast(gspca_dev
, ctrl
->val
);
394 case V4L2_CID_AUTOGAIN
:
395 if (gspca_dev
->exposure
->is_new
|| (ctrl
->is_new
&& ctrl
->val
))
396 setexposure(gspca_dev
, gspca_dev
->exposure
->val
);
397 if (gspca_dev
->gain
->is_new
|| (ctrl
->is_new
&& ctrl
->val
))
398 setgain(gspca_dev
, gspca_dev
->gain
->val
);
401 sethvflip(gspca_dev
, sd
->hflip
->val
, 1);
406 return gspca_dev
->usb_err
;
409 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
413 /* this function is called at probe time */
414 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
416 struct sd
*sd
= (struct sd
*) gspca_dev
;
417 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
419 gspca_dev
->vdev
.ctrl_handler
= hdl
;
420 v4l2_ctrl_handler_init(hdl
, 5);
422 sd
->contrast
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
423 V4L2_CID_CONTRAST
, 0, 15, 1, 7);
424 gspca_dev
->autogain
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
425 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
426 gspca_dev
->exposure
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
427 V4L2_CID_EXPOSURE
, 2, 63, 1,
428 PAC7311_EXPOSURE_DEFAULT
);
429 gspca_dev
->gain
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
430 V4L2_CID_GAIN
, 0, 244, 1,
431 PAC7311_GAIN_DEFAULT
);
432 sd
->hflip
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
433 V4L2_CID_HFLIP
, 0, 1, 1, 0);
436 pr_err("Could not initialize controls\n");
440 v4l2_ctrl_auto_cluster(3, &gspca_dev
->autogain
, 0, false);
444 /* -- start the camera -- */
445 static int sd_start(struct gspca_dev
*gspca_dev
)
447 struct sd
*sd
= (struct sd
*) gspca_dev
;
451 reg_w_var(gspca_dev
, start_7311
,
452 page4_7311
, sizeof(page4_7311
));
453 setcontrast(gspca_dev
, v4l2_ctrl_g_ctrl(sd
->contrast
));
454 setgain(gspca_dev
, v4l2_ctrl_g_ctrl(gspca_dev
->gain
));
455 setexposure(gspca_dev
, v4l2_ctrl_g_ctrl(gspca_dev
->exposure
));
456 sethvflip(gspca_dev
, v4l2_ctrl_g_ctrl(sd
->hflip
), 1);
458 /* set correct resolution */
459 switch (gspca_dev
->cam
.cam_mode
[(int) gspca_dev
->curr_mode
].priv
) {
460 case 2: /* 160x120 */
461 reg_w(gspca_dev
, 0xff, 0x01);
462 reg_w(gspca_dev
, 0x17, 0x20);
463 reg_w(gspca_dev
, 0x87, 0x10);
465 case 1: /* 320x240 */
466 reg_w(gspca_dev
, 0xff, 0x01);
467 reg_w(gspca_dev
, 0x17, 0x30);
468 reg_w(gspca_dev
, 0x87, 0x11);
470 case 0: /* 640x480 */
471 reg_w(gspca_dev
, 0xff, 0x01);
472 reg_w(gspca_dev
, 0x17, 0x00);
473 reg_w(gspca_dev
, 0x87, 0x12);
478 sd
->autogain_ignore_frames
= 0;
479 atomic_set(&sd
->avg_lum
, -1);
482 reg_w(gspca_dev
, 0xff, 0x01);
483 reg_w(gspca_dev
, 0x78, 0x05);
485 return gspca_dev
->usb_err
;
488 static void sd_stopN(struct gspca_dev
*gspca_dev
)
490 reg_w(gspca_dev
, 0xff, 0x04);
491 reg_w(gspca_dev
, 0x27, 0x80);
492 reg_w(gspca_dev
, 0x28, 0xca);
493 reg_w(gspca_dev
, 0x29, 0x53);
494 reg_w(gspca_dev
, 0x2a, 0x0e);
495 reg_w(gspca_dev
, 0xff, 0x01);
496 reg_w(gspca_dev
, 0x3e, 0x20);
497 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
498 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
499 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
502 static void do_autogain(struct gspca_dev
*gspca_dev
)
504 struct sd
*sd
= (struct sd
*) gspca_dev
;
505 int avg_lum
= atomic_read(&sd
->avg_lum
);
506 int desired_lum
, deadzone
;
514 if (sd
->autogain_ignore_frames
> 0)
515 sd
->autogain_ignore_frames
--;
516 else if (gspca_coarse_grained_expo_autogain(gspca_dev
, avg_lum
,
517 desired_lum
, deadzone
))
518 sd
->autogain_ignore_frames
= PAC_AUTOGAIN_IGNORE_FRAMES
;
521 /* JPEG header, part 1 */
522 static const unsigned char pac_jpeg_header1
[] = {
523 0xff, 0xd8, /* SOI: Start of Image */
525 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
526 0x00, 0x11, /* length = 17 bytes (including this length field) */
527 0x08 /* Precision: 8 */
528 /* 2 bytes is placed here: number of image lines */
529 /* 2 bytes is placed here: samples per line */
532 /* JPEG header, continued */
533 static const unsigned char pac_jpeg_header2
[] = {
534 0x03, /* Number of image components: 3 */
535 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
536 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
537 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
539 0xff, 0xda, /* SOS: Start Of Scan */
540 0x00, 0x0c, /* length = 12 bytes (including this length field) */
541 0x03, /* number of components: 3 */
542 0x01, 0x00, /* selector 1, table 0x00 */
543 0x02, 0x11, /* selector 2, table 0x11 */
544 0x03, 0x11, /* selector 3, table 0x11 */
545 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
546 0x00 /* Successive approximation: 0 */
549 static void pac_start_frame(struct gspca_dev
*gspca_dev
,
550 __u16 lines
, __u16 samples_per_line
)
552 unsigned char tmpbuf
[4];
554 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
555 pac_jpeg_header1
, sizeof(pac_jpeg_header1
));
557 tmpbuf
[0] = lines
>> 8;
558 tmpbuf
[1] = lines
& 0xff;
559 tmpbuf
[2] = samples_per_line
>> 8;
560 tmpbuf
[3] = samples_per_line
& 0xff;
562 gspca_frame_add(gspca_dev
, INTER_PACKET
,
563 tmpbuf
, sizeof(tmpbuf
));
564 gspca_frame_add(gspca_dev
, INTER_PACKET
,
565 pac_jpeg_header2
, sizeof(pac_jpeg_header2
));
568 /* this function is run at interrupt level */
569 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
570 u8
*data
, /* isoc packet */
571 int len
) /* iso packet length */
573 struct sd
*sd
= (struct sd
*) gspca_dev
;
577 sof
= pac_find_sof(gspca_dev
, &sd
->sof_read
, data
, len
);
579 int n
, lum_offset
, footer_length
;
582 * 6 bytes after the FF D9 EOF marker a number of lumination
583 * bytes are send corresponding to different parts of the
584 * image, the 14th and 15th byte after the EOF seem to
585 * correspond to the center of the image.
587 lum_offset
= 24 + sizeof pac_sof_marker
;
590 /* Finish decoding current frame */
591 n
= (sof
- data
) - (footer_length
+ sizeof pac_sof_marker
);
593 gspca_dev
->image_len
+= n
;
596 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, n
);
598 image
= gspca_dev
->image
;
600 && image
[gspca_dev
->image_len
- 2] == 0xff
601 && image
[gspca_dev
->image_len
- 1] == 0xd9)
602 gspca_frame_add(gspca_dev
, LAST_PACKET
, NULL
, 0);
608 /* Get average lumination */
609 if (gspca_dev
->last_packet_type
== LAST_PACKET
&&
611 atomic_set(&sd
->avg_lum
, data
[-lum_offset
] +
612 data
[-lum_offset
+ 1]);
614 atomic_set(&sd
->avg_lum
, -1);
616 /* Start the new frame with the jpeg header */
617 pac_start_frame(gspca_dev
,
618 gspca_dev
->height
, gspca_dev
->width
);
620 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
623 #if IS_ENABLED(CONFIG_INPUT)
624 static int sd_int_pkt_scan(struct gspca_dev
*gspca_dev
,
625 u8
*data
, /* interrupt packet data */
626 int len
) /* interrupt packet length */
634 if ((data0
== 0x00 && data1
== 0x11) ||
635 (data0
== 0x22 && data1
== 0x33) ||
636 (data0
== 0x44 && data1
== 0x55) ||
637 (data0
== 0x66 && data1
== 0x77) ||
638 (data0
== 0x88 && data1
== 0x99) ||
639 (data0
== 0xaa && data1
== 0xbb) ||
640 (data0
== 0xcc && data1
== 0xdd) ||
641 (data0
== 0xee && data1
== 0xff)) {
642 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 1);
643 input_sync(gspca_dev
->input_dev
);
644 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 0);
645 input_sync(gspca_dev
->input_dev
);
654 static const struct sd_desc sd_desc
= {
658 .init_controls
= sd_init_controls
,
661 .pkt_scan
= sd_pkt_scan
,
662 .dq_callback
= do_autogain
,
663 #if IS_ENABLED(CONFIG_INPUT)
664 .int_pkt_scan
= sd_int_pkt_scan
,
668 /* -- module initialisation -- */
669 static const struct usb_device_id device_table
[] = {
670 {USB_DEVICE(0x093a, 0x2600)},
671 {USB_DEVICE(0x093a, 0x2601)},
672 {USB_DEVICE(0x093a, 0x2603)},
673 {USB_DEVICE(0x093a, 0x2608)},
674 {USB_DEVICE(0x093a, 0x260e)},
675 {USB_DEVICE(0x093a, 0x260f)},
678 MODULE_DEVICE_TABLE(usb
, device_table
);
680 /* -- device connect -- */
681 static int sd_probe(struct usb_interface
*intf
,
682 const struct usb_device_id
*id
)
684 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
688 static struct usb_driver sd_driver
= {
690 .id_table
= device_table
,
692 .disconnect
= gspca_disconnect
,
694 .suspend
= gspca_suspend
,
695 .resume
= gspca_resume
,
696 .reset_resume
= gspca_resume
,
700 module_usb_driver(sd_driver
);