Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      Pixart PAC7311 library
0004  *      Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
0005  *
0006  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
0007  */
0008 
0009 /* Some documentation about various registers as determined by trial and error.
0010  *
0011  * Register page 1:
0012  *
0013  * Address  Description
0014  * 0x08     Unknown compressor related, must always be 8 except when not
0015  *      in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
0016  * 0x1b     Auto white balance related, bit 0 is AWB enable (inverted)
0017  *      bits 345 seem to toggle per color gains on/off (inverted)
0018  * 0x78     Global control, bit 6 controls the LED (inverted)
0019  * 0x80     Compression balance, interesting settings:
0020  *      0x01 Use this to allow the camera to switch to higher compr.
0021  *           on the fly. Needed to stay within bandwidth @ 640x480@30
0022  *      0x1c From usb captures under Windows for 640x480
0023  *      0x2a Values >= this switch the camera to a lower compression,
0024  *           using the same table for both luminance and chrominance.
0025  *           This gives a sharper picture. Usable only at 640x480@ <
0026  *           15 fps or 320x240 / 160x120. Note currently the driver
0027  *           does not use this as the quality gain is small and the
0028  *           generated JPG-s are only understood by v4l-utils >= 0.8.9
0029  *      0x3f From usb captures under Windows for 320x240
0030  *      0x69 From usb captures under Windows for 160x120
0031  *
0032  * Register page 4:
0033  *
0034  * Address  Description
0035  * 0x02     Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
0036  *      the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
0037  * 0x0f     Master gain 1-245, low value = high gain
0038  * 0x10     Another gain 0-15, limited influence (1-2x gain I guess)
0039  * 0x21     Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
0040  *      Note setting vflip disabled leads to a much lower image quality,
0041  *      so we always vflip, and tell userspace to flip it back
0042  * 0x27     Seems to toggle various gains on / off, Setting bit 7 seems to
0043  *      completely disable the analog amplification block. Set to 0x68
0044  *      for max gain, 0x14 for minimal gain.
0045  */
0046 
0047 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0048 
0049 #define MODULE_NAME "pac7311"
0050 
0051 #include <linux/input.h>
0052 #include "gspca.h"
0053 /* Include pac common sof detection functions */
0054 #include "pac_common.h"
0055 
0056 #define PAC7311_GAIN_DEFAULT     122
0057 #define PAC7311_EXPOSURE_DEFAULT   3 /* 20 fps, avoid using high compr. */
0058 
0059 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
0060 MODULE_DESCRIPTION("Pixart PAC7311");
0061 MODULE_LICENSE("GPL");
0062 
0063 struct sd {
0064     struct gspca_dev gspca_dev;     /* !! must be the first item */
0065 
0066     struct v4l2_ctrl *contrast;
0067     struct v4l2_ctrl *hflip;
0068 
0069     u8 sof_read;
0070     u8 autogain_ignore_frames;
0071 
0072     atomic_t avg_lum;
0073 };
0074 
0075 static const struct v4l2_pix_format vga_mode[] = {
0076     {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
0077         .bytesperline = 160,
0078         .sizeimage = 160 * 120 * 3 / 8 + 590,
0079         .colorspace = V4L2_COLORSPACE_JPEG,
0080         .priv = 2},
0081     {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
0082         .bytesperline = 320,
0083         .sizeimage = 320 * 240 * 3 / 8 + 590,
0084         .colorspace = V4L2_COLORSPACE_JPEG,
0085         .priv = 1},
0086     {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
0087         .bytesperline = 640,
0088         .sizeimage = 640 * 480 * 3 / 8 + 590,
0089         .colorspace = V4L2_COLORSPACE_JPEG,
0090         .priv = 0},
0091 };
0092 
0093 #define LOAD_PAGE4      254
0094 #define END_OF_SEQUENCE     0
0095 
0096 static const __u8 init_7311[] = {
0097     0xff, 0x01,
0098     0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
0099     0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
0100     0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
0101     0xff, 0x04,
0102     0x27, 0x80,
0103     0x28, 0xca,
0104     0x29, 0x53,
0105     0x2a, 0x0e,
0106     0xff, 0x01,
0107     0x3e, 0x20,
0108 };
0109 
0110 static const __u8 start_7311[] = {
0111 /*  index, len, [value]* */
0112     0xff, 1,    0x01,       /* page 1 */
0113     0x02, 43,   0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
0114             0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
0115             0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
0116             0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
0117             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0118             0x00, 0x00, 0x00,
0119     0x3e, 42,   0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
0120             0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
0121             0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
0122             0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
0123             0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
0124             0xd0, 0xff,
0125     0x78, 6,    0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
0126     0x7f, 18,   0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
0127             0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
0128             0x18, 0x20,
0129     0x96, 3,    0x01, 0x08, 0x04,
0130     0xa0, 4,    0x44, 0x44, 0x44, 0x04,
0131     0xf0, 13,   0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
0132             0x3f, 0x00, 0x0a, 0x01, 0x00,
0133     0xff, 1,    0x04,       /* page 4 */
0134     0, LOAD_PAGE4,          /* load the page 4 */
0135     0x11, 1,    0x01,
0136     0, END_OF_SEQUENCE      /* end of sequence */
0137 };
0138 
0139 #define SKIP        0xaa
0140 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
0141 static const __u8 page4_7311[] = {
0142     SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
0143     0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
0144     0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
0145     0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
0146     SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
0147     0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
0148     0x23, 0x28, 0x04, 0x11, 0x00, 0x00
0149 };
0150 
0151 static void reg_w_buf(struct gspca_dev *gspca_dev,
0152           __u8 index,
0153           const u8 *buffer, int len)
0154 {
0155     int ret;
0156 
0157     if (gspca_dev->usb_err < 0)
0158         return;
0159     memcpy(gspca_dev->usb_buf, buffer, len);
0160     ret = usb_control_msg(gspca_dev->dev,
0161             usb_sndctrlpipe(gspca_dev->dev, 0),
0162             0,      /* request */
0163             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0164             0,      /* value */
0165             index, gspca_dev->usb_buf, len,
0166             500);
0167     if (ret < 0) {
0168         pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
0169                index, ret);
0170         gspca_dev->usb_err = ret;
0171     }
0172 }
0173 
0174 
0175 static void reg_w(struct gspca_dev *gspca_dev,
0176           __u8 index,
0177           __u8 value)
0178 {
0179     int ret;
0180 
0181     if (gspca_dev->usb_err < 0)
0182         return;
0183     gspca_dev->usb_buf[0] = value;
0184     ret = usb_control_msg(gspca_dev->dev,
0185             usb_sndctrlpipe(gspca_dev->dev, 0),
0186             0,          /* request */
0187             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0188             0, index, gspca_dev->usb_buf, 1,
0189             500);
0190     if (ret < 0) {
0191         pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
0192                index, value, ret);
0193         gspca_dev->usb_err = ret;
0194     }
0195 }
0196 
0197 static void reg_w_seq(struct gspca_dev *gspca_dev,
0198         const __u8 *seq, int len)
0199 {
0200     while (--len >= 0) {
0201         reg_w(gspca_dev, seq[0], seq[1]);
0202         seq += 2;
0203     }
0204 }
0205 
0206 /* load the beginning of a page */
0207 static void reg_w_page(struct gspca_dev *gspca_dev,
0208             const __u8 *page, int len)
0209 {
0210     int index;
0211     int ret = 0;
0212 
0213     if (gspca_dev->usb_err < 0)
0214         return;
0215     for (index = 0; index < len; index++) {
0216         if (page[index] == SKIP)        /* skip this index */
0217             continue;
0218         gspca_dev->usb_buf[0] = page[index];
0219         ret = usb_control_msg(gspca_dev->dev,
0220                 usb_sndctrlpipe(gspca_dev->dev, 0),
0221                 0,          /* request */
0222             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0223                 0, index, gspca_dev->usb_buf, 1,
0224                 500);
0225         if (ret < 0) {
0226             pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
0227                    index, page[index], ret);
0228             gspca_dev->usb_err = ret;
0229             break;
0230         }
0231     }
0232 }
0233 
0234 /* output a variable sequence */
0235 static void reg_w_var(struct gspca_dev *gspca_dev,
0236             const __u8 *seq,
0237             const __u8 *page4, unsigned int page4_len)
0238 {
0239     int index, len;
0240 
0241     for (;;) {
0242         index = *seq++;
0243         len = *seq++;
0244         switch (len) {
0245         case END_OF_SEQUENCE:
0246             return;
0247         case LOAD_PAGE4:
0248             reg_w_page(gspca_dev, page4, page4_len);
0249             break;
0250         default:
0251             if (len > USB_BUF_SZ) {
0252                 gspca_err(gspca_dev, "Incorrect variable sequence\n");
0253                 return;
0254             }
0255             while (len > 0) {
0256                 if (len < 8) {
0257                     reg_w_buf(gspca_dev,
0258                         index, seq, len);
0259                     seq += len;
0260                     break;
0261                 }
0262                 reg_w_buf(gspca_dev, index, seq, 8);
0263                 seq += 8;
0264                 index += 8;
0265                 len -= 8;
0266             }
0267         }
0268     }
0269     /* not reached */
0270 }
0271 
0272 /* this function is called at probe time for pac7311 */
0273 static int sd_config(struct gspca_dev *gspca_dev,
0274             const struct usb_device_id *id)
0275 {
0276     struct cam *cam = &gspca_dev->cam;
0277 
0278     cam->cam_mode = vga_mode;
0279     cam->nmodes = ARRAY_SIZE(vga_mode);
0280     cam->input_flags = V4L2_IN_ST_VFLIP;
0281 
0282     return 0;
0283 }
0284 
0285 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
0286 {
0287     reg_w(gspca_dev, 0xff, 0x04);
0288     reg_w(gspca_dev, 0x10, val);
0289     /* load registers to sensor (Bit 0, auto clear) */
0290     reg_w(gspca_dev, 0x11, 0x01);
0291 }
0292 
0293 static void setgain(struct gspca_dev *gspca_dev, s32 val)
0294 {
0295     reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
0296     reg_w(gspca_dev, 0x0e, 0x00);
0297     reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
0298 
0299     /* load registers to sensor (Bit 0, auto clear) */
0300     reg_w(gspca_dev, 0x11, 0x01);
0301 }
0302 
0303 static void setexposure(struct gspca_dev *gspca_dev, s32 val)
0304 {
0305     reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
0306     reg_w(gspca_dev, 0x02, val);
0307 
0308     /* load registers to sensor (Bit 0, auto clear) */
0309     reg_w(gspca_dev, 0x11, 0x01);
0310 
0311     /*
0312      * Page 1 register 8 must always be 0x08 except when not in
0313      *  640x480 mode and page 4 reg 2 <= 3 then it must be 9
0314      */
0315     reg_w(gspca_dev, 0xff, 0x01);
0316     if (gspca_dev->pixfmt.width != 640 && val <= 3)
0317         reg_w(gspca_dev, 0x08, 0x09);
0318     else
0319         reg_w(gspca_dev, 0x08, 0x08);
0320 
0321     /*
0322      * Page1 register 80 sets the compression balance, normally we
0323      * want / use 0x1c, but for 640x480@30fps we must allow the
0324      * camera to use higher compression or we may run out of
0325      * bandwidth.
0326      */
0327     if (gspca_dev->pixfmt.width == 640 && val == 2)
0328         reg_w(gspca_dev, 0x80, 0x01);
0329     else
0330         reg_w(gspca_dev, 0x80, 0x1c);
0331 
0332     /* load registers to sensor (Bit 0, auto clear) */
0333     reg_w(gspca_dev, 0x11, 0x01);
0334 }
0335 
0336 static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
0337 {
0338     __u8 data;
0339 
0340     reg_w(gspca_dev, 0xff, 0x04);           /* page 4 */
0341     data = (hflip ? 0x04 : 0x00) |
0342            (vflip ? 0x08 : 0x00);
0343     reg_w(gspca_dev, 0x21, data);
0344 
0345     /* load registers to sensor (Bit 0, auto clear) */
0346     reg_w(gspca_dev, 0x11, 0x01);
0347 }
0348 
0349 /* this function is called at probe and resume time for pac7311 */
0350 static int sd_init(struct gspca_dev *gspca_dev)
0351 {
0352     reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
0353     return gspca_dev->usb_err;
0354 }
0355 
0356 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0357 {
0358     struct gspca_dev *gspca_dev =
0359         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0360     struct sd *sd = (struct sd *)gspca_dev;
0361 
0362     gspca_dev->usb_err = 0;
0363 
0364     if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
0365         /* when switching to autogain set defaults to make sure
0366            we are on a valid point of the autogain gain /
0367            exposure knee graph, and give this change time to
0368            take effect before doing autogain. */
0369         gspca_dev->exposure->val    = PAC7311_EXPOSURE_DEFAULT;
0370         gspca_dev->gain->val        = PAC7311_GAIN_DEFAULT;
0371         sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
0372     }
0373 
0374     if (!gspca_dev->streaming)
0375         return 0;
0376 
0377     switch (ctrl->id) {
0378     case V4L2_CID_CONTRAST:
0379         setcontrast(gspca_dev, ctrl->val);
0380         break;
0381     case V4L2_CID_AUTOGAIN:
0382         if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
0383             setexposure(gspca_dev, gspca_dev->exposure->val);
0384         if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
0385             setgain(gspca_dev, gspca_dev->gain->val);
0386         break;
0387     case V4L2_CID_HFLIP:
0388         sethvflip(gspca_dev, sd->hflip->val, 1);
0389         break;
0390     default:
0391         return -EINVAL;
0392     }
0393     return gspca_dev->usb_err;
0394 }
0395 
0396 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0397     .s_ctrl = sd_s_ctrl,
0398 };
0399 
0400 /* this function is called at probe time */
0401 static int sd_init_controls(struct gspca_dev *gspca_dev)
0402 {
0403     struct sd *sd = (struct sd *) gspca_dev;
0404     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0405 
0406     gspca_dev->vdev.ctrl_handler = hdl;
0407     v4l2_ctrl_handler_init(hdl, 5);
0408 
0409     sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0410                     V4L2_CID_CONTRAST, 0, 15, 1, 7);
0411     gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0412                     V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
0413     gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0414                     V4L2_CID_EXPOSURE, 2, 63, 1,
0415                     PAC7311_EXPOSURE_DEFAULT);
0416     gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0417                     V4L2_CID_GAIN, 0, 244, 1,
0418                     PAC7311_GAIN_DEFAULT);
0419     sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0420         V4L2_CID_HFLIP, 0, 1, 1, 0);
0421 
0422     if (hdl->error) {
0423         pr_err("Could not initialize controls\n");
0424         return hdl->error;
0425     }
0426 
0427     v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
0428     return 0;
0429 }
0430 
0431 /* -- start the camera -- */
0432 static int sd_start(struct gspca_dev *gspca_dev)
0433 {
0434     struct sd *sd = (struct sd *) gspca_dev;
0435 
0436     sd->sof_read = 0;
0437 
0438     reg_w_var(gspca_dev, start_7311,
0439         page4_7311, sizeof(page4_7311));
0440     setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
0441     setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
0442     setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
0443     sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
0444 
0445     /* set correct resolution */
0446     switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
0447     case 2:                 /* 160x120 */
0448         reg_w(gspca_dev, 0xff, 0x01);
0449         reg_w(gspca_dev, 0x17, 0x20);
0450         reg_w(gspca_dev, 0x87, 0x10);
0451         break;
0452     case 1:                 /* 320x240 */
0453         reg_w(gspca_dev, 0xff, 0x01);
0454         reg_w(gspca_dev, 0x17, 0x30);
0455         reg_w(gspca_dev, 0x87, 0x11);
0456         break;
0457     case 0:                 /* 640x480 */
0458         reg_w(gspca_dev, 0xff, 0x01);
0459         reg_w(gspca_dev, 0x17, 0x00);
0460         reg_w(gspca_dev, 0x87, 0x12);
0461         break;
0462     }
0463 
0464     sd->sof_read = 0;
0465     sd->autogain_ignore_frames = 0;
0466     atomic_set(&sd->avg_lum, -1);
0467 
0468     /* start stream */
0469     reg_w(gspca_dev, 0xff, 0x01);
0470     reg_w(gspca_dev, 0x78, 0x05);
0471 
0472     return gspca_dev->usb_err;
0473 }
0474 
0475 static void sd_stopN(struct gspca_dev *gspca_dev)
0476 {
0477     reg_w(gspca_dev, 0xff, 0x04);
0478     reg_w(gspca_dev, 0x27, 0x80);
0479     reg_w(gspca_dev, 0x28, 0xca);
0480     reg_w(gspca_dev, 0x29, 0x53);
0481     reg_w(gspca_dev, 0x2a, 0x0e);
0482     reg_w(gspca_dev, 0xff, 0x01);
0483     reg_w(gspca_dev, 0x3e, 0x20);
0484     reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
0485     reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
0486     reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
0487 }
0488 
0489 static void do_autogain(struct gspca_dev *gspca_dev)
0490 {
0491     struct sd *sd = (struct sd *) gspca_dev;
0492     int avg_lum = atomic_read(&sd->avg_lum);
0493     int desired_lum, deadzone;
0494 
0495     if (avg_lum == -1)
0496         return;
0497 
0498     desired_lum = 170;
0499     deadzone = 20;
0500 
0501     if (sd->autogain_ignore_frames > 0)
0502         sd->autogain_ignore_frames--;
0503     else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
0504                             desired_lum, deadzone))
0505         sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
0506 }
0507 
0508 /* JPEG header, part 1 */
0509 static const unsigned char pac_jpeg_header1[] = {
0510   0xff, 0xd8,       /* SOI: Start of Image */
0511 
0512   0xff, 0xc0,       /* SOF0: Start of Frame (Baseline DCT) */
0513   0x00, 0x11,       /* length = 17 bytes (including this length field) */
0514   0x08          /* Precision: 8 */
0515   /* 2 bytes is placed here: number of image lines */
0516   /* 2 bytes is placed here: samples per line */
0517 };
0518 
0519 /* JPEG header, continued */
0520 static const unsigned char pac_jpeg_header2[] = {
0521   0x03,         /* Number of image components: 3 */
0522   0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
0523   0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
0524   0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
0525 
0526   0xff, 0xda,       /* SOS: Start Of Scan */
0527   0x00, 0x0c,       /* length = 12 bytes (including this length field) */
0528   0x03,         /* number of components: 3 */
0529   0x01, 0x00,       /* selector 1, table 0x00 */
0530   0x02, 0x11,       /* selector 2, table 0x11 */
0531   0x03, 0x11,       /* selector 3, table 0x11 */
0532   0x00, 0x3f,       /* Spectral selection: 0 .. 63 */
0533   0x00          /* Successive approximation: 0 */
0534 };
0535 
0536 static void pac_start_frame(struct gspca_dev *gspca_dev,
0537         __u16 lines, __u16 samples_per_line)
0538 {
0539     unsigned char tmpbuf[4];
0540 
0541     gspca_frame_add(gspca_dev, FIRST_PACKET,
0542         pac_jpeg_header1, sizeof(pac_jpeg_header1));
0543 
0544     tmpbuf[0] = lines >> 8;
0545     tmpbuf[1] = lines & 0xff;
0546     tmpbuf[2] = samples_per_line >> 8;
0547     tmpbuf[3] = samples_per_line & 0xff;
0548 
0549     gspca_frame_add(gspca_dev, INTER_PACKET,
0550         tmpbuf, sizeof(tmpbuf));
0551     gspca_frame_add(gspca_dev, INTER_PACKET,
0552         pac_jpeg_header2, sizeof(pac_jpeg_header2));
0553 }
0554 
0555 /* this function is run at interrupt level */
0556 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0557             u8 *data,           /* isoc packet */
0558             int len)            /* iso packet length */
0559 {
0560     struct sd *sd = (struct sd *) gspca_dev;
0561     u8 *image;
0562     unsigned char *sof;
0563 
0564     sof = pac_find_sof(gspca_dev, &sd->sof_read, data, len);
0565     if (sof) {
0566         int n, lum_offset, footer_length;
0567 
0568         /*
0569          * 6 bytes after the FF D9 EOF marker a number of lumination
0570          * bytes are send corresponding to different parts of the
0571          * image, the 14th and 15th byte after the EOF seem to
0572          * correspond to the center of the image.
0573          */
0574         lum_offset = 24 + sizeof pac_sof_marker;
0575         footer_length = 26;
0576 
0577         /* Finish decoding current frame */
0578         n = (sof - data) - (footer_length + sizeof pac_sof_marker);
0579         if (n < 0) {
0580             gspca_dev->image_len += n;
0581             n = 0;
0582         } else {
0583             gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
0584         }
0585         image = gspca_dev->image;
0586         if (image != NULL
0587          && image[gspca_dev->image_len - 2] == 0xff
0588          && image[gspca_dev->image_len - 1] == 0xd9)
0589             gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0590 
0591         n = sof - data;
0592         len -= n;
0593         data = sof;
0594 
0595         /* Get average lumination */
0596         if (gspca_dev->last_packet_type == LAST_PACKET &&
0597                 n >= lum_offset)
0598             atomic_set(&sd->avg_lum, data[-lum_offset] +
0599                         data[-lum_offset + 1]);
0600         else
0601             atomic_set(&sd->avg_lum, -1);
0602 
0603         /* Start the new frame with the jpeg header */
0604         pac_start_frame(gspca_dev,
0605             gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
0606     }
0607     gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0608 }
0609 
0610 #if IS_ENABLED(CONFIG_INPUT)
0611 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
0612             u8 *data,       /* interrupt packet data */
0613             int len)        /* interrupt packet length */
0614 {
0615     int ret = -EINVAL;
0616     u8 data0, data1;
0617 
0618     if (len == 2) {
0619         data0 = data[0];
0620         data1 = data[1];
0621         if ((data0 == 0x00 && data1 == 0x11) ||
0622             (data0 == 0x22 && data1 == 0x33) ||
0623             (data0 == 0x44 && data1 == 0x55) ||
0624             (data0 == 0x66 && data1 == 0x77) ||
0625             (data0 == 0x88 && data1 == 0x99) ||
0626             (data0 == 0xaa && data1 == 0xbb) ||
0627             (data0 == 0xcc && data1 == 0xdd) ||
0628             (data0 == 0xee && data1 == 0xff)) {
0629             input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
0630             input_sync(gspca_dev->input_dev);
0631             input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
0632             input_sync(gspca_dev->input_dev);
0633             ret = 0;
0634         }
0635     }
0636 
0637     return ret;
0638 }
0639 #endif
0640 
0641 static const struct sd_desc sd_desc = {
0642     .name = MODULE_NAME,
0643     .config = sd_config,
0644     .init = sd_init,
0645     .init_controls = sd_init_controls,
0646     .start = sd_start,
0647     .stopN = sd_stopN,
0648     .pkt_scan = sd_pkt_scan,
0649     .dq_callback = do_autogain,
0650 #if IS_ENABLED(CONFIG_INPUT)
0651     .int_pkt_scan = sd_int_pkt_scan,
0652 #endif
0653 };
0654 
0655 /* -- module initialisation -- */
0656 static const struct usb_device_id device_table[] = {
0657     {USB_DEVICE(0x093a, 0x2600)},
0658     {USB_DEVICE(0x093a, 0x2601)},
0659     {USB_DEVICE(0x093a, 0x2603)},
0660     {USB_DEVICE(0x093a, 0x2608)},
0661     {USB_DEVICE(0x093a, 0x260e)},
0662     {USB_DEVICE(0x093a, 0x260f)},
0663     {}
0664 };
0665 MODULE_DEVICE_TABLE(usb, device_table);
0666 
0667 /* -- device connect -- */
0668 static int sd_probe(struct usb_interface *intf,
0669             const struct usb_device_id *id)
0670 {
0671     return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0672                 THIS_MODULE);
0673 }
0674 
0675 static struct usb_driver sd_driver = {
0676     .name = MODULE_NAME,
0677     .id_table = device_table,
0678     .probe = sd_probe,
0679     .disconnect = gspca_disconnect,
0680 #ifdef CONFIG_PM
0681     .suspend = gspca_suspend,
0682     .resume = gspca_resume,
0683     .reset_resume = gspca_resume,
0684 #endif
0685 };
0686 
0687 module_usb_driver(sd_driver);