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(dev: gspca_dev->dev,
161 usb_sndctrlpipe(gspca_dev->dev, 0),
162 request: 0, /* request */
163 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
164 value: 0, /* value */
165 index, data: gspca_dev->usb_buf, size: len,
166 timeout: 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(dev: gspca_dev->dev,
185 usb_sndctrlpipe(gspca_dev->dev, 0),
186 request: 0, /* request */
187 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
188 value: 0, index, data: gspca_dev->usb_buf, size: 1,
189 timeout: 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, index: seq[0], value: 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(dev: gspca_dev->dev,
220 usb_sndctrlpipe(gspca_dev->dev, 0),
221 request: 0, /* request */
222 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
223 value: 0, index, data: gspca_dev->usb_buf, size: 1,
224 timeout: 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, page: page4, len: 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, buffer: seq, len);
259 seq += len;
260 break;
261 }
262 reg_w_buf(gspca_dev, index, buffer: seq, len: 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, index: 0xff, value: 0x04);
288 reg_w(gspca_dev, index: 0x10, value: val);
289 /* load registers to sensor (Bit 0, auto clear) */
290 reg_w(gspca_dev, index: 0x11, value: 0x01);
291}
292
293static void setgain(struct gspca_dev *gspca_dev, s32 val)
294{
295 reg_w(gspca_dev, index: 0xff, value: 0x04); /* page 4 */
296 reg_w(gspca_dev, index: 0x0e, value: 0x00);
297 reg_w(gspca_dev, index: 0x0f, value: gspca_dev->gain->maximum - val + 1);
298
299 /* load registers to sensor (Bit 0, auto clear) */
300 reg_w(gspca_dev, index: 0x11, value: 0x01);
301}
302
303static void setexposure(struct gspca_dev *gspca_dev, s32 val)
304{
305 reg_w(gspca_dev, index: 0xff, value: 0x04); /* page 4 */
306 reg_w(gspca_dev, index: 0x02, value: val);
307
308 /* load registers to sensor (Bit 0, auto clear) */
309 reg_w(gspca_dev, index: 0x11, value: 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, index: 0xff, value: 0x01);
316 if (gspca_dev->pixfmt.width != 640 && val <= 3)
317 reg_w(gspca_dev, index: 0x08, value: 0x09);
318 else
319 reg_w(gspca_dev, index: 0x08, value: 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, index: 0x80, value: 0x01);
329 else
330 reg_w(gspca_dev, index: 0x80, value: 0x1c);
331
332 /* load registers to sensor (Bit 0, auto clear) */
333 reg_w(gspca_dev, index: 0x11, value: 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, index: 0xff, value: 0x04); /* page 4 */
341 data = (hflip ? 0x04 : 0x00) |
342 (vflip ? 0x08 : 0x00);
343 reg_w(gspca_dev, index: 0x21, value: data);
344
345 /* load registers to sensor (Bit 0, auto clear) */
346 reg_w(gspca_dev, index: 0x11, value: 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, seq: init_7311, len: 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, val: 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, val: gspca_dev->exposure->val);
384 if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
385 setgain(gspca_dev, val: gspca_dev->gain->val);
386 break;
387 case V4L2_CID_HFLIP:
388 sethvflip(gspca_dev, hflip: sd->hflip->val, vflip: 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, ops: &sd_ctrl_ops,
410 V4L2_CID_CONTRAST, min: 0, max: 15, step: 1, def: 7);
411 gspca_dev->autogain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
412 V4L2_CID_AUTOGAIN, min: 0, max: 1, step: 1, def: 1);
413 gspca_dev->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
414 V4L2_CID_EXPOSURE, min: 2, max: 63, step: 1,
415 PAC7311_EXPOSURE_DEFAULT);
416 gspca_dev->gain = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
417 V4L2_CID_GAIN, min: 0, max: 244, step: 1,
418 PAC7311_GAIN_DEFAULT);
419 sd->hflip = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops,
420 V4L2_CID_HFLIP, min: 0, max: 1, step: 1, def: 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(ncontrols: 3, controls: &gspca_dev->autogain, manual_val: 0, set_volatile: 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, seq: start_7311,
439 page4: page4_7311, page4_len: sizeof(page4_7311));
440 setcontrast(gspca_dev, val: v4l2_ctrl_g_ctrl(ctrl: sd->contrast));
441 setgain(gspca_dev, val: v4l2_ctrl_g_ctrl(ctrl: gspca_dev->gain));
442 setexposure(gspca_dev, val: v4l2_ctrl_g_ctrl(ctrl: gspca_dev->exposure));
443 sethvflip(gspca_dev, hflip: v4l2_ctrl_g_ctrl(ctrl: sd->hflip), vflip: 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, index: 0xff, value: 0x01);
449 reg_w(gspca_dev, index: 0x17, value: 0x20);
450 reg_w(gspca_dev, index: 0x87, value: 0x10);
451 break;
452 case 1: /* 320x240 */
453 reg_w(gspca_dev, index: 0xff, value: 0x01);
454 reg_w(gspca_dev, index: 0x17, value: 0x30);
455 reg_w(gspca_dev, index: 0x87, value: 0x11);
456 break;
457 case 0: /* 640x480 */
458 reg_w(gspca_dev, index: 0xff, value: 0x01);
459 reg_w(gspca_dev, index: 0x17, value: 0x00);
460 reg_w(gspca_dev, index: 0x87, value: 0x12);
461 break;
462 }
463
464 sd->sof_read = 0;
465 sd->autogain_ignore_frames = 0;
466 atomic_set(v: &sd->avg_lum, i: -1);
467
468 /* start stream */
469 reg_w(gspca_dev, index: 0xff, value: 0x01);
470 reg_w(gspca_dev, index: 0x78, value: 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, index: 0xff, value: 0x04);
478 reg_w(gspca_dev, index: 0x27, value: 0x80);
479 reg_w(gspca_dev, index: 0x28, value: 0xca);
480 reg_w(gspca_dev, index: 0x29, value: 0x53);
481 reg_w(gspca_dev, index: 0x2a, value: 0x0e);
482 reg_w(gspca_dev, index: 0xff, value: 0x01);
483 reg_w(gspca_dev, index: 0x3e, value: 0x20);
484 reg_w(gspca_dev, index: 0x78, value: 0x44); /* Bit_0=start stream, Bit_6=LED */
485 reg_w(gspca_dev, index: 0x78, value: 0x44); /* Bit_0=start stream, Bit_6=LED */
486 reg_w(gspca_dev, index: 0x78, value: 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(v: &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_avg_lum: 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, packet_type: FIRST_PACKET,
542 data: pac_jpeg_header1, len: 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, packet_type: INTER_PACKET,
550 data: tmpbuf, len: sizeof(tmpbuf));
551 gspca_frame_add(gspca_dev, packet_type: INTER_PACKET,
552 data: pac_jpeg_header2, len: 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, sof_read: &sd->sof_read, m: 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, packet_type: INTER_PACKET, data, len: 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, packet_type: LAST_PACKET, NULL, len: 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(v: &sd->avg_lum, i: data[-lum_offset] +
599 data[-lum_offset + 1]);
600 else
601 atomic_set(v: &sd->avg_lum, i: -1);
602
603 /* Start the new frame with the jpeg header */
604 pac_start_frame(gspca_dev,
605 lines: gspca_dev->pixfmt.height, samples_per_line: gspca_dev->pixfmt.width);
606 }
607 gspca_frame_add(gspca_dev, packet_type: 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(dev: gspca_dev->input_dev, KEY_CAMERA, value: 1);
630 input_sync(dev: gspca_dev->input_dev);
631 input_report_key(dev: gspca_dev->input_dev, KEY_CAMERA, value: 0);
632 input_sync(dev: 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: &sd_desc, dev_size: 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);
688

source code of linux/drivers/media/usb/gspca/pac7311.c