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.
18 /* Some documentation about various registers as determined by trial and error.
23 * 0x08 Unknown compressor related, must always be 8 except when not
24 * in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
25 * 0x1b Auto white balance related, bit 0 is AWB enable (inverted)
26 * bits 345 seem to toggle per color gains on/off (inverted)
27 * 0x78 Global control, bit 6 controls the LED (inverted)
28 * 0x80 Compression balance, interesting settings:
29 * 0x01 Use this to allow the camera to switch to higher compr.
30 * on the fly. Needed to stay within bandwidth @ 640x480@30
31 * 0x1c From usb captures under Windows for 640x480
32 * 0x2a Values >= this switch the camera to a lower compression,
33 * using the same table for both luminance and chrominance.
34 * This gives a sharper picture. Usable only at 640x480@ <
35 * 15 fps or 320x240 / 160x120. Note currently the driver
36 * does not use this as the quality gain is small and the
37 * generated JPG-s are only understood by v4l-utils >= 0.8.9
38 * 0x3f From usb captures under Windows for 320x240
39 * 0x69 From usb captures under Windows for 160x120
44 * 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
45 * the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
46 * 0x0f Master gain 1-245, low value = high gain
47 * 0x10 Another gain 0-15, limited influence (1-2x gain I guess)
48 * 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
49 * Note setting vflip disabled leads to a much lower image quality,
50 * so we always vflip, and tell userspace to flip it back
51 * 0x27 Seems to toggle various gains on / off, Setting bit 7 seems to
52 * completely disable the analog amplification block. Set to 0x68
53 * for max gain, 0x14 for minimal gain.
56 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
58 #define MODULE_NAME "pac7311"
60 #include <linux/input.h>
62 /* Include pac common sof detection functions */
63 #include "pac_common.h"
65 #define PAC7311_GAIN_DEFAULT 122
66 #define PAC7311_EXPOSURE_DEFAULT 3 /* 20 fps, avoid using high compr. */
68 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
69 MODULE_DESCRIPTION("Pixart PAC7311");
70 MODULE_LICENSE("GPL");
73 struct gspca_dev gspca_dev
; /* !! must be the first item */
75 struct v4l2_ctrl
*contrast
;
76 struct v4l2_ctrl
*hflip
;
79 u8 autogain_ignore_frames
;
84 static const struct v4l2_pix_format vga_mode
[] = {
85 {160, 120, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
87 .sizeimage
= 160 * 120 * 3 / 8 + 590,
88 .colorspace
= V4L2_COLORSPACE_JPEG
,
90 {320, 240, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
92 .sizeimage
= 320 * 240 * 3 / 8 + 590,
93 .colorspace
= V4L2_COLORSPACE_JPEG
,
95 {640, 480, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
97 .sizeimage
= 640 * 480 * 3 / 8 + 590,
98 .colorspace
= V4L2_COLORSPACE_JPEG
,
102 #define LOAD_PAGE4 254
103 #define END_OF_SEQUENCE 0
105 static const __u8 init_7311
[] = {
107 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
108 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
109 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
119 static const __u8 start_7311
[] = {
120 /* index, len, [value]* */
121 0xff, 1, 0x01, /* page 1 */
122 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
123 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
124 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
125 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
129 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
130 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
131 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
132 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
134 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
135 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
136 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
138 0x96, 3, 0x01, 0x08, 0x04,
139 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
140 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
141 0x3f, 0x00, 0x0a, 0x01, 0x00,
142 0xff, 1, 0x04, /* page 4 */
143 0, LOAD_PAGE4
, /* load the page 4 */
145 0, END_OF_SEQUENCE
/* end of sequence */
149 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
150 static const __u8 page4_7311
[] = {
151 SKIP
, SKIP
, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
152 0x09, 0x00, SKIP
, SKIP
, 0x07, 0x00, 0x00, 0x62,
153 0x08, SKIP
, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP
,
155 SKIP
, 0x00, 0x08, SKIP
, 0x03, SKIP
, 0x00, 0x68,
156 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
157 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
160 static void reg_w_buf(struct gspca_dev
*gspca_dev
,
162 const u8
*buffer
, int len
)
166 if (gspca_dev
->usb_err
< 0)
168 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
169 ret
= usb_control_msg(gspca_dev
->dev
,
170 usb_sndctrlpipe(gspca_dev
->dev
, 0),
172 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
174 index
, gspca_dev
->usb_buf
, len
,
177 pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
179 gspca_dev
->usb_err
= ret
;
184 static void reg_w(struct gspca_dev
*gspca_dev
,
190 if (gspca_dev
->usb_err
< 0)
192 gspca_dev
->usb_buf
[0] = value
;
193 ret
= usb_control_msg(gspca_dev
->dev
,
194 usb_sndctrlpipe(gspca_dev
->dev
, 0),
196 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
197 0, index
, gspca_dev
->usb_buf
, 1,
200 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
202 gspca_dev
->usb_err
= ret
;
206 static void reg_w_seq(struct gspca_dev
*gspca_dev
,
207 const __u8
*seq
, int len
)
210 reg_w(gspca_dev
, seq
[0], seq
[1]);
215 /* load the beginning of a page */
216 static void reg_w_page(struct gspca_dev
*gspca_dev
,
217 const __u8
*page
, int len
)
222 if (gspca_dev
->usb_err
< 0)
224 for (index
= 0; index
< len
; index
++) {
225 if (page
[index
] == SKIP
) /* skip this index */
227 gspca_dev
->usb_buf
[0] = page
[index
];
228 ret
= usb_control_msg(gspca_dev
->dev
,
229 usb_sndctrlpipe(gspca_dev
->dev
, 0),
231 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
232 0, index
, gspca_dev
->usb_buf
, 1,
235 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
236 index
, page
[index
], ret
);
237 gspca_dev
->usb_err
= ret
;
243 /* output a variable sequence */
244 static void reg_w_var(struct gspca_dev
*gspca_dev
,
246 const __u8
*page4
, unsigned int page4_len
)
254 case END_OF_SEQUENCE
:
257 reg_w_page(gspca_dev
, page4
, page4_len
);
260 if (len
> USB_BUF_SZ
) {
261 gspca_err(gspca_dev
, "Incorrect variable sequence\n");
271 reg_w_buf(gspca_dev
, index
, seq
, 8);
281 /* this function is called at probe time for pac7311 */
282 static int sd_config(struct gspca_dev
*gspca_dev
,
283 const struct usb_device_id
*id
)
285 struct cam
*cam
= &gspca_dev
->cam
;
287 cam
->cam_mode
= vga_mode
;
288 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
289 cam
->input_flags
= V4L2_IN_ST_VFLIP
;
294 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
296 reg_w(gspca_dev
, 0xff, 0x04);
297 reg_w(gspca_dev
, 0x10, val
);
298 /* load registers to sensor (Bit 0, auto clear) */
299 reg_w(gspca_dev
, 0x11, 0x01);
302 static void setgain(struct gspca_dev
*gspca_dev
, s32 val
)
304 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
305 reg_w(gspca_dev
, 0x0e, 0x00);
306 reg_w(gspca_dev
, 0x0f, gspca_dev
->gain
->maximum
- val
+ 1);
308 /* load registers to sensor (Bit 0, auto clear) */
309 reg_w(gspca_dev
, 0x11, 0x01);
312 static void setexposure(struct gspca_dev
*gspca_dev
, s32 val
)
314 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
315 reg_w(gspca_dev
, 0x02, val
);
317 /* load registers to sensor (Bit 0, auto clear) */
318 reg_w(gspca_dev
, 0x11, 0x01);
321 * Page 1 register 8 must always be 0x08 except when not in
322 * 640x480 mode and page 4 reg 2 <= 3 then it must be 9
324 reg_w(gspca_dev
, 0xff, 0x01);
325 if (gspca_dev
->pixfmt
.width
!= 640 && val
<= 3)
326 reg_w(gspca_dev
, 0x08, 0x09);
328 reg_w(gspca_dev
, 0x08, 0x08);
331 * Page1 register 80 sets the compression balance, normally we
332 * want / use 0x1c, but for 640x480@30fps we must allow the
333 * camera to use higher compression or we may run out of
336 if (gspca_dev
->pixfmt
.width
== 640 && val
== 2)
337 reg_w(gspca_dev
, 0x80, 0x01);
339 reg_w(gspca_dev
, 0x80, 0x1c);
341 /* load registers to sensor (Bit 0, auto clear) */
342 reg_w(gspca_dev
, 0x11, 0x01);
345 static void sethvflip(struct gspca_dev
*gspca_dev
, s32 hflip
, s32 vflip
)
349 reg_w(gspca_dev
, 0xff, 0x04); /* page 4 */
350 data
= (hflip
? 0x04 : 0x00) |
351 (vflip
? 0x08 : 0x00);
352 reg_w(gspca_dev
, 0x21, data
);
354 /* load registers to sensor (Bit 0, auto clear) */
355 reg_w(gspca_dev
, 0x11, 0x01);
358 /* this function is called at probe and resume time for pac7311 */
359 static int sd_init(struct gspca_dev
*gspca_dev
)
361 reg_w_seq(gspca_dev
, init_7311
, sizeof(init_7311
)/2);
362 return gspca_dev
->usb_err
;
365 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
367 struct gspca_dev
*gspca_dev
=
368 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
369 struct sd
*sd
= (struct sd
*)gspca_dev
;
371 gspca_dev
->usb_err
= 0;
373 if (ctrl
->id
== V4L2_CID_AUTOGAIN
&& ctrl
->is_new
&& ctrl
->val
) {
374 /* when switching to autogain set defaults to make sure
375 we are on a valid point of the autogain gain /
376 exposure knee graph, and give this change time to
377 take effect before doing autogain. */
378 gspca_dev
->exposure
->val
= PAC7311_EXPOSURE_DEFAULT
;
379 gspca_dev
->gain
->val
= PAC7311_GAIN_DEFAULT
;
380 sd
->autogain_ignore_frames
= PAC_AUTOGAIN_IGNORE_FRAMES
;
383 if (!gspca_dev
->streaming
)
387 case V4L2_CID_CONTRAST
:
388 setcontrast(gspca_dev
, ctrl
->val
);
390 case V4L2_CID_AUTOGAIN
:
391 if (gspca_dev
->exposure
->is_new
|| (ctrl
->is_new
&& ctrl
->val
))
392 setexposure(gspca_dev
, gspca_dev
->exposure
->val
);
393 if (gspca_dev
->gain
->is_new
|| (ctrl
->is_new
&& ctrl
->val
))
394 setgain(gspca_dev
, gspca_dev
->gain
->val
);
397 sethvflip(gspca_dev
, sd
->hflip
->val
, 1);
402 return gspca_dev
->usb_err
;
405 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
409 /* this function is called at probe time */
410 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
412 struct sd
*sd
= (struct sd
*) gspca_dev
;
413 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
415 gspca_dev
->vdev
.ctrl_handler
= hdl
;
416 v4l2_ctrl_handler_init(hdl
, 5);
418 sd
->contrast
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
419 V4L2_CID_CONTRAST
, 0, 15, 1, 7);
420 gspca_dev
->autogain
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
421 V4L2_CID_AUTOGAIN
, 0, 1, 1, 1);
422 gspca_dev
->exposure
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
423 V4L2_CID_EXPOSURE
, 2, 63, 1,
424 PAC7311_EXPOSURE_DEFAULT
);
425 gspca_dev
->gain
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
426 V4L2_CID_GAIN
, 0, 244, 1,
427 PAC7311_GAIN_DEFAULT
);
428 sd
->hflip
= v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
429 V4L2_CID_HFLIP
, 0, 1, 1, 0);
432 pr_err("Could not initialize controls\n");
436 v4l2_ctrl_auto_cluster(3, &gspca_dev
->autogain
, 0, false);
440 /* -- start the camera -- */
441 static int sd_start(struct gspca_dev
*gspca_dev
)
443 struct sd
*sd
= (struct sd
*) gspca_dev
;
447 reg_w_var(gspca_dev
, start_7311
,
448 page4_7311
, sizeof(page4_7311
));
449 setcontrast(gspca_dev
, v4l2_ctrl_g_ctrl(sd
->contrast
));
450 setgain(gspca_dev
, v4l2_ctrl_g_ctrl(gspca_dev
->gain
));
451 setexposure(gspca_dev
, v4l2_ctrl_g_ctrl(gspca_dev
->exposure
));
452 sethvflip(gspca_dev
, v4l2_ctrl_g_ctrl(sd
->hflip
), 1);
454 /* set correct resolution */
455 switch (gspca_dev
->cam
.cam_mode
[(int) gspca_dev
->curr_mode
].priv
) {
456 case 2: /* 160x120 */
457 reg_w(gspca_dev
, 0xff, 0x01);
458 reg_w(gspca_dev
, 0x17, 0x20);
459 reg_w(gspca_dev
, 0x87, 0x10);
461 case 1: /* 320x240 */
462 reg_w(gspca_dev
, 0xff, 0x01);
463 reg_w(gspca_dev
, 0x17, 0x30);
464 reg_w(gspca_dev
, 0x87, 0x11);
466 case 0: /* 640x480 */
467 reg_w(gspca_dev
, 0xff, 0x01);
468 reg_w(gspca_dev
, 0x17, 0x00);
469 reg_w(gspca_dev
, 0x87, 0x12);
474 sd
->autogain_ignore_frames
= 0;
475 atomic_set(&sd
->avg_lum
, -1);
478 reg_w(gspca_dev
, 0xff, 0x01);
479 reg_w(gspca_dev
, 0x78, 0x05);
481 return gspca_dev
->usb_err
;
484 static void sd_stopN(struct gspca_dev
*gspca_dev
)
486 reg_w(gspca_dev
, 0xff, 0x04);
487 reg_w(gspca_dev
, 0x27, 0x80);
488 reg_w(gspca_dev
, 0x28, 0xca);
489 reg_w(gspca_dev
, 0x29, 0x53);
490 reg_w(gspca_dev
, 0x2a, 0x0e);
491 reg_w(gspca_dev
, 0xff, 0x01);
492 reg_w(gspca_dev
, 0x3e, 0x20);
493 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
494 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
495 reg_w(gspca_dev
, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
498 static void do_autogain(struct gspca_dev
*gspca_dev
)
500 struct sd
*sd
= (struct sd
*) gspca_dev
;
501 int avg_lum
= atomic_read(&sd
->avg_lum
);
502 int desired_lum
, deadzone
;
510 if (sd
->autogain_ignore_frames
> 0)
511 sd
->autogain_ignore_frames
--;
512 else if (gspca_coarse_grained_expo_autogain(gspca_dev
, avg_lum
,
513 desired_lum
, deadzone
))
514 sd
->autogain_ignore_frames
= PAC_AUTOGAIN_IGNORE_FRAMES
;
517 /* JPEG header, part 1 */
518 static const unsigned char pac_jpeg_header1
[] = {
519 0xff, 0xd8, /* SOI: Start of Image */
521 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
522 0x00, 0x11, /* length = 17 bytes (including this length field) */
523 0x08 /* Precision: 8 */
524 /* 2 bytes is placed here: number of image lines */
525 /* 2 bytes is placed here: samples per line */
528 /* JPEG header, continued */
529 static const unsigned char pac_jpeg_header2
[] = {
530 0x03, /* Number of image components: 3 */
531 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
532 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
533 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
535 0xff, 0xda, /* SOS: Start Of Scan */
536 0x00, 0x0c, /* length = 12 bytes (including this length field) */
537 0x03, /* number of components: 3 */
538 0x01, 0x00, /* selector 1, table 0x00 */
539 0x02, 0x11, /* selector 2, table 0x11 */
540 0x03, 0x11, /* selector 3, table 0x11 */
541 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
542 0x00 /* Successive approximation: 0 */
545 static void pac_start_frame(struct gspca_dev
*gspca_dev
,
546 __u16 lines
, __u16 samples_per_line
)
548 unsigned char tmpbuf
[4];
550 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
551 pac_jpeg_header1
, sizeof(pac_jpeg_header1
));
553 tmpbuf
[0] = lines
>> 8;
554 tmpbuf
[1] = lines
& 0xff;
555 tmpbuf
[2] = samples_per_line
>> 8;
556 tmpbuf
[3] = samples_per_line
& 0xff;
558 gspca_frame_add(gspca_dev
, INTER_PACKET
,
559 tmpbuf
, sizeof(tmpbuf
));
560 gspca_frame_add(gspca_dev
, INTER_PACKET
,
561 pac_jpeg_header2
, sizeof(pac_jpeg_header2
));
564 /* this function is run at interrupt level */
565 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
566 u8
*data
, /* isoc packet */
567 int len
) /* iso packet length */
569 struct sd
*sd
= (struct sd
*) gspca_dev
;
573 sof
= pac_find_sof(gspca_dev
, &sd
->sof_read
, data
, len
);
575 int n
, lum_offset
, footer_length
;
578 * 6 bytes after the FF D9 EOF marker a number of lumination
579 * bytes are send corresponding to different parts of the
580 * image, the 14th and 15th byte after the EOF seem to
581 * correspond to the center of the image.
583 lum_offset
= 24 + sizeof pac_sof_marker
;
586 /* Finish decoding current frame */
587 n
= (sof
- data
) - (footer_length
+ sizeof pac_sof_marker
);
589 gspca_dev
->image_len
+= n
;
592 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, n
);
594 image
= gspca_dev
->image
;
596 && image
[gspca_dev
->image_len
- 2] == 0xff
597 && image
[gspca_dev
->image_len
- 1] == 0xd9)
598 gspca_frame_add(gspca_dev
, LAST_PACKET
, NULL
, 0);
604 /* Get average lumination */
605 if (gspca_dev
->last_packet_type
== LAST_PACKET
&&
607 atomic_set(&sd
->avg_lum
, data
[-lum_offset
] +
608 data
[-lum_offset
+ 1]);
610 atomic_set(&sd
->avg_lum
, -1);
612 /* Start the new frame with the jpeg header */
613 pac_start_frame(gspca_dev
,
614 gspca_dev
->pixfmt
.height
, gspca_dev
->pixfmt
.width
);
616 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
619 #if IS_ENABLED(CONFIG_INPUT)
620 static int sd_int_pkt_scan(struct gspca_dev
*gspca_dev
,
621 u8
*data
, /* interrupt packet data */
622 int len
) /* interrupt packet length */
630 if ((data0
== 0x00 && data1
== 0x11) ||
631 (data0
== 0x22 && data1
== 0x33) ||
632 (data0
== 0x44 && data1
== 0x55) ||
633 (data0
== 0x66 && data1
== 0x77) ||
634 (data0
== 0x88 && data1
== 0x99) ||
635 (data0
== 0xaa && data1
== 0xbb) ||
636 (data0
== 0xcc && data1
== 0xdd) ||
637 (data0
== 0xee && data1
== 0xff)) {
638 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 1);
639 input_sync(gspca_dev
->input_dev
);
640 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 0);
641 input_sync(gspca_dev
->input_dev
);
650 static const struct sd_desc sd_desc
= {
654 .init_controls
= sd_init_controls
,
657 .pkt_scan
= sd_pkt_scan
,
658 .dq_callback
= do_autogain
,
659 #if IS_ENABLED(CONFIG_INPUT)
660 .int_pkt_scan
= sd_int_pkt_scan
,
664 /* -- module initialisation -- */
665 static const struct usb_device_id device_table
[] = {
666 {USB_DEVICE(0x093a, 0x2600)},
667 {USB_DEVICE(0x093a, 0x2601)},
668 {USB_DEVICE(0x093a, 0x2603)},
669 {USB_DEVICE(0x093a, 0x2608)},
670 {USB_DEVICE(0x093a, 0x260e)},
671 {USB_DEVICE(0x093a, 0x260f)},
674 MODULE_DEVICE_TABLE(usb
, device_table
);
676 /* -- device connect -- */
677 static int sd_probe(struct usb_interface
*intf
,
678 const struct usb_device_id
*id
)
680 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
684 static struct usb_driver sd_driver
= {
686 .id_table
= device_table
,
688 .disconnect
= gspca_disconnect
,
690 .suspend
= gspca_suspend
,
691 .resume
= gspca_resume
,
692 .reset_resume
= gspca_resume
,
696 module_usb_driver(sd_driver
);