Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
0003  * Subdriver core
0004  *
0005  * 2009/09/24 Olivier Lorin <o.lorin@laposte.net>
0006  * GSPCA by Jean-Francois Moine <http://moinejf.free.fr>
0007  * Thanks BUGabundo and Malmostoso for your amazing help!
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include "gspca.h"
0013 #include "gl860.h"
0014 
0015 MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
0016 MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
0017 MODULE_LICENSE("GPL");
0018 
0019 /*======================== static function declarations ====================*/
0020 
0021 static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
0022 
0023 static int  sd_config(struct gspca_dev *gspca_dev,
0024             const struct usb_device_id *id);
0025 static int  sd_init(struct gspca_dev *gspca_dev);
0026 static int  sd_isoc_init(struct gspca_dev *gspca_dev);
0027 static int  sd_start(struct gspca_dev *gspca_dev);
0028 static void sd_stop0(struct gspca_dev *gspca_dev);
0029 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0030             u8 *data, int len);
0031 static void sd_callback(struct gspca_dev *gspca_dev);
0032 
0033 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
0034                 u16 vendor_id, u16 product_id);
0035 
0036 /*============================ driver options ==============================*/
0037 
0038 static s32 AC50Hz = 0xff;
0039 module_param(AC50Hz, int, 0644);
0040 MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
0041 
0042 static char sensor[7];
0043 module_param_string(sensor, sensor, sizeof(sensor), 0644);
0044 MODULE_PARM_DESC(sensor,
0045         " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
0046 
0047 /*============================ webcam controls =============================*/
0048 
0049 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0050 {
0051     struct gspca_dev *gspca_dev =
0052         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0053     struct sd *sd = (struct sd *) gspca_dev;
0054 
0055     switch (ctrl->id) {
0056     case V4L2_CID_BRIGHTNESS:
0057         sd->vcur.brightness = ctrl->val;
0058         break;
0059     case V4L2_CID_CONTRAST:
0060         sd->vcur.contrast = ctrl->val;
0061         break;
0062     case V4L2_CID_SATURATION:
0063         sd->vcur.saturation = ctrl->val;
0064         break;
0065     case V4L2_CID_HUE:
0066         sd->vcur.hue = ctrl->val;
0067         break;
0068     case V4L2_CID_GAMMA:
0069         sd->vcur.gamma = ctrl->val;
0070         break;
0071     case V4L2_CID_HFLIP:
0072         sd->vcur.mirror = ctrl->val;
0073         break;
0074     case V4L2_CID_VFLIP:
0075         sd->vcur.flip = ctrl->val;
0076         break;
0077     case V4L2_CID_POWER_LINE_FREQUENCY:
0078         sd->vcur.AC50Hz = ctrl->val;
0079         break;
0080     case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
0081         sd->vcur.whitebal = ctrl->val;
0082         break;
0083     case V4L2_CID_SHARPNESS:
0084         sd->vcur.sharpness = ctrl->val;
0085         break;
0086     case V4L2_CID_BACKLIGHT_COMPENSATION:
0087         sd->vcur.backlight = ctrl->val;
0088         break;
0089     default:
0090         return -EINVAL;
0091     }
0092 
0093     if (gspca_dev->streaming)
0094         sd->waitSet = 1;
0095 
0096     return 0;
0097 }
0098 
0099 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0100     .s_ctrl = sd_s_ctrl,
0101 };
0102 
0103 static int sd_init_controls(struct gspca_dev *gspca_dev)
0104 {
0105     struct sd *sd = (struct sd *) gspca_dev;
0106     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0107 
0108     gspca_dev->vdev.ctrl_handler = hdl;
0109     v4l2_ctrl_handler_init(hdl, 11);
0110 
0111     if (sd->vmax.brightness)
0112         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS,
0113                   0, sd->vmax.brightness, 1,
0114                   sd->vcur.brightness);
0115 
0116     if (sd->vmax.contrast)
0117         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST,
0118                   0, sd->vmax.contrast, 1,
0119                   sd->vcur.contrast);
0120 
0121     if (sd->vmax.saturation)
0122         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SATURATION,
0123                   0, sd->vmax.saturation, 1,
0124                   sd->vcur.saturation);
0125 
0126     if (sd->vmax.hue)
0127         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HUE,
0128                   0, sd->vmax.hue, 1, sd->vcur.hue);
0129 
0130     if (sd->vmax.gamma)
0131         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAMMA,
0132                   0, sd->vmax.gamma, 1, sd->vcur.gamma);
0133 
0134     if (sd->vmax.mirror)
0135         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HFLIP,
0136                   0, sd->vmax.mirror, 1, sd->vcur.mirror);
0137 
0138     if (sd->vmax.flip)
0139         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_VFLIP,
0140                   0, sd->vmax.flip, 1, sd->vcur.flip);
0141 
0142     if (sd->vmax.AC50Hz)
0143         v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
0144                   V4L2_CID_POWER_LINE_FREQUENCY,
0145                   sd->vmax.AC50Hz, 0, sd->vcur.AC50Hz);
0146 
0147     if (sd->vmax.whitebal)
0148         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0149                   V4L2_CID_WHITE_BALANCE_TEMPERATURE,
0150                   0, sd->vmax.whitebal, 1, sd->vcur.whitebal);
0151 
0152     if (sd->vmax.sharpness)
0153         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SHARPNESS,
0154                   0, sd->vmax.sharpness, 1,
0155                   sd->vcur.sharpness);
0156 
0157     if (sd->vmax.backlight)
0158         v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0159                   V4L2_CID_BACKLIGHT_COMPENSATION,
0160                   0, sd->vmax.backlight, 1,
0161                   sd->vcur.backlight);
0162 
0163     if (hdl->error) {
0164         pr_err("Could not initialize controls\n");
0165         return hdl->error;
0166     }
0167 
0168     return 0;
0169 }
0170 
0171 /*==================== sud-driver structure initialisation =================*/
0172 
0173 static const struct sd_desc sd_desc_mi1320 = {
0174     .name        = MODULE_NAME,
0175     .config      = sd_config,
0176     .init        = sd_init,
0177     .init_controls = sd_init_controls,
0178     .isoc_init   = sd_isoc_init,
0179     .start       = sd_start,
0180     .stop0       = sd_stop0,
0181     .pkt_scan    = sd_pkt_scan,
0182     .dq_callback = sd_callback,
0183 };
0184 
0185 static const struct sd_desc sd_desc_mi2020 = {
0186     .name        = MODULE_NAME,
0187     .config      = sd_config,
0188     .init        = sd_init,
0189     .init_controls = sd_init_controls,
0190     .isoc_init   = sd_isoc_init,
0191     .start       = sd_start,
0192     .stop0       = sd_stop0,
0193     .pkt_scan    = sd_pkt_scan,
0194     .dq_callback = sd_callback,
0195 };
0196 
0197 static const struct sd_desc sd_desc_ov2640 = {
0198     .name        = MODULE_NAME,
0199     .config      = sd_config,
0200     .init        = sd_init,
0201     .init_controls = sd_init_controls,
0202     .isoc_init   = sd_isoc_init,
0203     .start       = sd_start,
0204     .stop0       = sd_stop0,
0205     .pkt_scan    = sd_pkt_scan,
0206     .dq_callback = sd_callback,
0207 };
0208 
0209 static const struct sd_desc sd_desc_ov9655 = {
0210     .name        = MODULE_NAME,
0211     .config      = sd_config,
0212     .init        = sd_init,
0213     .init_controls = sd_init_controls,
0214     .isoc_init   = sd_isoc_init,
0215     .start       = sd_start,
0216     .stop0       = sd_stop0,
0217     .pkt_scan    = sd_pkt_scan,
0218     .dq_callback = sd_callback,
0219 };
0220 
0221 /*=========================== sub-driver image sizes =======================*/
0222 
0223 static struct v4l2_pix_format mi2020_mode[] = {
0224     { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0225         .bytesperline = 640,
0226         .sizeimage = 640 * 480,
0227         .colorspace = V4L2_COLORSPACE_SRGB,
0228         .priv = 0
0229     },
0230     { 800,  598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0231         .bytesperline = 800,
0232         .sizeimage = 800 * 598,
0233         .colorspace = V4L2_COLORSPACE_SRGB,
0234         .priv = 1
0235     },
0236     {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0237         .bytesperline = 1280,
0238         .sizeimage = 1280 * 1024,
0239         .colorspace = V4L2_COLORSPACE_SRGB,
0240         .priv = 2
0241     },
0242     {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0243         .bytesperline = 1600,
0244         .sizeimage = 1600 * 1198,
0245         .colorspace = V4L2_COLORSPACE_SRGB,
0246         .priv = 3
0247     },
0248 };
0249 
0250 static struct v4l2_pix_format ov2640_mode[] = {
0251     { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0252         .bytesperline = 640,
0253         .sizeimage = 640 * 480,
0254         .colorspace = V4L2_COLORSPACE_SRGB,
0255         .priv = 0
0256     },
0257     { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0258         .bytesperline = 800,
0259         .sizeimage = 800 * 600,
0260         .colorspace = V4L2_COLORSPACE_SRGB,
0261         .priv = 1
0262     },
0263     {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0264         .bytesperline = 1280,
0265         .sizeimage = 1280 * 960,
0266         .colorspace = V4L2_COLORSPACE_SRGB,
0267         .priv = 2
0268     },
0269     {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0270         .bytesperline = 1600,
0271         .sizeimage = 1600 * 1200,
0272         .colorspace = V4L2_COLORSPACE_SRGB,
0273         .priv = 3
0274     },
0275 };
0276 
0277 static struct v4l2_pix_format mi1320_mode[] = {
0278     { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0279         .bytesperline = 640,
0280         .sizeimage = 640 * 480,
0281         .colorspace = V4L2_COLORSPACE_SRGB,
0282         .priv = 0
0283     },
0284     { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0285         .bytesperline = 800,
0286         .sizeimage = 800 * 600,
0287         .colorspace = V4L2_COLORSPACE_SRGB,
0288         .priv = 1
0289     },
0290     {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0291         .bytesperline = 1280,
0292         .sizeimage = 1280 * 960,
0293         .colorspace = V4L2_COLORSPACE_SRGB,
0294         .priv = 2
0295     },
0296 };
0297 
0298 static struct v4l2_pix_format ov9655_mode[] = {
0299     { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0300         .bytesperline = 640,
0301         .sizeimage = 640 * 480,
0302         .colorspace = V4L2_COLORSPACE_SRGB,
0303         .priv = 0
0304     },
0305     {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
0306         .bytesperline = 1280,
0307         .sizeimage = 1280 * 960,
0308         .colorspace = V4L2_COLORSPACE_SRGB,
0309         .priv = 1
0310     },
0311 };
0312 
0313 /*========================= sud-driver functions ===========================*/
0314 
0315 /* This function is called at probe time */
0316 static int sd_config(struct gspca_dev *gspca_dev,
0317             const struct usb_device_id *id)
0318 {
0319     struct sd *sd = (struct sd *) gspca_dev;
0320     struct cam *cam;
0321     u16 vendor_id, product_id;
0322 
0323     /* Get USB VendorID and ProductID */
0324     vendor_id  = id->idVendor;
0325     product_id = id->idProduct;
0326 
0327     sd->nbRightUp = 1;
0328     sd->nbIm = -1;
0329 
0330     sd->sensor = 0xff;
0331     if (strcmp(sensor, "MI1320") == 0)
0332         sd->sensor = ID_MI1320;
0333     else if (strcmp(sensor, "OV2640") == 0)
0334         sd->sensor = ID_OV2640;
0335     else if (strcmp(sensor, "OV9655") == 0)
0336         sd->sensor = ID_OV9655;
0337     else if (strcmp(sensor, "MI2020") == 0)
0338         sd->sensor = ID_MI2020;
0339 
0340     /* Get sensor and set the suitable init/start/../stop functions */
0341     if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
0342         return -1;
0343 
0344     cam = &gspca_dev->cam;
0345 
0346     switch (sd->sensor) {
0347     case ID_MI1320:
0348         gspca_dev->sd_desc = &sd_desc_mi1320;
0349         cam->cam_mode = mi1320_mode;
0350         cam->nmodes = ARRAY_SIZE(mi1320_mode);
0351         dev_init_settings   = mi1320_init_settings;
0352         break;
0353 
0354     case ID_MI2020:
0355         gspca_dev->sd_desc = &sd_desc_mi2020;
0356         cam->cam_mode = mi2020_mode;
0357         cam->nmodes = ARRAY_SIZE(mi2020_mode);
0358         dev_init_settings   = mi2020_init_settings;
0359         break;
0360 
0361     case ID_OV2640:
0362         gspca_dev->sd_desc = &sd_desc_ov2640;
0363         cam->cam_mode = ov2640_mode;
0364         cam->nmodes = ARRAY_SIZE(ov2640_mode);
0365         dev_init_settings   = ov2640_init_settings;
0366         break;
0367 
0368     case ID_OV9655:
0369         gspca_dev->sd_desc = &sd_desc_ov9655;
0370         cam->cam_mode = ov9655_mode;
0371         cam->nmodes = ARRAY_SIZE(ov9655_mode);
0372         dev_init_settings   = ov9655_init_settings;
0373         break;
0374     }
0375 
0376     dev_init_settings(gspca_dev);
0377     if (AC50Hz != 0xff)
0378         ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
0379 
0380     return 0;
0381 }
0382 
0383 /* This function is called at probe time after sd_config */
0384 static int sd_init(struct gspca_dev *gspca_dev)
0385 {
0386     struct sd *sd = (struct sd *) gspca_dev;
0387 
0388     return sd->dev_init_at_startup(gspca_dev);
0389 }
0390 
0391 /* This function is called before to choose the alt setting */
0392 static int sd_isoc_init(struct gspca_dev *gspca_dev)
0393 {
0394     struct sd *sd = (struct sd *) gspca_dev;
0395 
0396     return sd->dev_configure_alt(gspca_dev);
0397 }
0398 
0399 /* This function is called to start the webcam */
0400 static int sd_start(struct gspca_dev *gspca_dev)
0401 {
0402     struct sd *sd = (struct sd *) gspca_dev;
0403 
0404     return sd->dev_init_pre_alt(gspca_dev);
0405 }
0406 
0407 /* This function is called to stop the webcam */
0408 static void sd_stop0(struct gspca_dev *gspca_dev)
0409 {
0410     struct sd *sd = (struct sd *) gspca_dev;
0411 
0412     if (!sd->gspca_dev.present)
0413         return;
0414 
0415     return sd->dev_post_unset_alt(gspca_dev);
0416 }
0417 
0418 /* This function is called when an image is being received */
0419 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0420             u8 *data, int len)
0421 {
0422     struct sd *sd = (struct sd *) gspca_dev;
0423     static s32 nSkipped;
0424 
0425     s32 mode = (s32) gspca_dev->curr_mode;
0426     s32 nToSkip =
0427         sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
0428 
0429     /* Test only against 0202h, so endianness does not matter */
0430     switch (*(s16 *) data) {
0431     case 0x0202:        /* End of frame, start a new one */
0432         gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0433         nSkipped = 0;
0434         if (sd->nbIm >= 0 && sd->nbIm < 10)
0435             sd->nbIm++;
0436         gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
0437         break;
0438 
0439     default:
0440         data += 2;
0441         len  -= 2;
0442         if (nSkipped + len <= nToSkip)
0443             nSkipped += len;
0444         else {
0445             if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
0446                 data += nToSkip - nSkipped;
0447                 len  -= nToSkip - nSkipped;
0448                 nSkipped = nToSkip + 1;
0449             }
0450             gspca_frame_add(gspca_dev,
0451                 INTER_PACKET, data, len);
0452         }
0453         break;
0454     }
0455 }
0456 
0457 /* This function is called when an image has been read */
0458 /* This function is used to monitor webcam orientation */
0459 static void sd_callback(struct gspca_dev *gspca_dev)
0460 {
0461     struct sd *sd = (struct sd *) gspca_dev;
0462 
0463     if (!_OV9655_) {
0464         u8 state;
0465         u8 upsideDown;
0466 
0467         /* Probe sensor orientation */
0468         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
0469 
0470         /* C8/40 means upside-down (looking backwards) */
0471         /* D8/50 means right-up (looking onwards) */
0472         upsideDown = (state == 0xc8 || state == 0x40);
0473 
0474         if (upsideDown && sd->nbRightUp > -4) {
0475             if (sd->nbRightUp > 0)
0476                 sd->nbRightUp = 0;
0477             if (sd->nbRightUp == -3) {
0478                 sd->mirrorMask = 1;
0479                 sd->waitSet = 1;
0480             }
0481             sd->nbRightUp--;
0482         }
0483         if (!upsideDown && sd->nbRightUp < 4) {
0484             if (sd->nbRightUp  < 0)
0485                 sd->nbRightUp = 0;
0486             if (sd->nbRightUp == 3) {
0487                 sd->mirrorMask = 0;
0488                 sd->waitSet = 1;
0489             }
0490             sd->nbRightUp++;
0491         }
0492     }
0493 
0494     if (sd->waitSet)
0495         sd->dev_camera_settings(gspca_dev);
0496 }
0497 
0498 /*=================== USB driver structure initialisation ==================*/
0499 
0500 static const struct usb_device_id device_table[] = {
0501     {USB_DEVICE(0x05e3, 0x0503)},
0502     {USB_DEVICE(0x05e3, 0xf191)},
0503     {}
0504 };
0505 
0506 MODULE_DEVICE_TABLE(usb, device_table);
0507 
0508 static int sd_probe(struct usb_interface *intf,
0509                 const struct usb_device_id *id)
0510 {
0511     return gspca_dev_probe(intf, id,
0512             &sd_desc_mi1320, sizeof(struct sd), THIS_MODULE);
0513 }
0514 
0515 static void sd_disconnect(struct usb_interface *intf)
0516 {
0517     gspca_disconnect(intf);
0518 }
0519 
0520 static struct usb_driver sd_driver = {
0521     .name       = MODULE_NAME,
0522     .id_table   = device_table,
0523     .probe      = sd_probe,
0524     .disconnect = sd_disconnect,
0525 #ifdef CONFIG_PM
0526     .suspend    = gspca_suspend,
0527     .resume     = gspca_resume,
0528     .reset_resume = gspca_resume,
0529 #endif
0530 };
0531 
0532 /*====================== Init and Exit module functions ====================*/
0533 
0534 module_usb_driver(sd_driver);
0535 
0536 /*==========================================================================*/
0537 
0538 int gl860_RTx(struct gspca_dev *gspca_dev,
0539         unsigned char pref, u32 req, u16 val, u16 index,
0540         s32 len, void *pdata)
0541 {
0542     struct usb_device *udev = gspca_dev->dev;
0543     s32 r = 0;
0544 
0545     if (pref == 0x40) { /* Send */
0546         if (len > 0) {
0547             memcpy(gspca_dev->usb_buf, pdata, len);
0548             r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0549                     req, pref, val, index,
0550                     gspca_dev->usb_buf,
0551                     len, 400 + 200 * (len > 1));
0552         } else {
0553             r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0554                     req, pref, val, index, NULL, len, 400);
0555         }
0556     } else { /* Receive */
0557         if (len > 0) {
0558             r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0559                     req, pref, val, index,
0560                     gspca_dev->usb_buf,
0561                     len, 400 + 200 * (len > 1));
0562             memcpy(pdata, gspca_dev->usb_buf, len);
0563         } else {
0564             gspca_err(gspca_dev, "zero-length read request\n");
0565             r = -EINVAL;
0566         }
0567     }
0568 
0569     if (r < 0)
0570         pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
0571                r, pref, req, val, index, len);
0572     else if (len > 1 && r < len)
0573         gspca_err(gspca_dev, "short ctrl transfer %d/%d\n", r, len);
0574 
0575     msleep(1);
0576 
0577     return r;
0578 }
0579 
0580 int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
0581 {
0582     int n;
0583 
0584     for (n = 0; n < len; n++) {
0585         if (tbl[n].idx != 0xffff)
0586             ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
0587                     tbl[n].idx, 0, NULL);
0588         else if (tbl[n].val == 0xffff)
0589             break;
0590         else
0591             msleep(tbl[n].val);
0592     }
0593     return n;
0594 }
0595 
0596 int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
0597                 int len, int n)
0598 {
0599     while (++n < len) {
0600         if (tbl[n].idx != 0xffff)
0601             ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
0602                     0, NULL);
0603         else if (tbl[n].val == 0xffff)
0604             break;
0605         else
0606             msleep(tbl[n].val);
0607     }
0608     return n;
0609 }
0610 
0611 void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
0612 {
0613     int n;
0614 
0615     for (n = 0; n < len; n++) {
0616         if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
0617             ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
0618                     3, tbl[n].data);
0619         else
0620             msleep(tbl[n].idx);
0621     }
0622 }
0623 
0624 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
0625                 u16 vendor_id, u16 product_id)
0626 {
0627     struct sd *sd = (struct sd *) gspca_dev;
0628     u8 probe, nb26, nb96, nOV, ntry;
0629 
0630     if (product_id == 0xf191)
0631         sd->sensor = ID_MI1320;
0632 
0633     if (sd->sensor == 0xff) {
0634         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
0635         ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
0636 
0637         ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
0638         msleep(3);
0639         ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
0640         msleep(3);
0641         ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
0642         msleep(3);
0643         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
0644         msleep(3);
0645         ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
0646         msleep(3);
0647         ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
0648         msleep(3);
0649         ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
0650         msleep(56);
0651 
0652         gspca_dbg(gspca_dev, D_PROBE, "probing for sensor MI2020 or OVXXXX\n");
0653         nOV = 0;
0654         for (ntry = 0; ntry < 4; ntry++) {
0655             ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
0656             msleep(3);
0657             ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
0658             msleep(3);
0659             ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
0660             msleep(10);
0661             ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
0662             gspca_dbg(gspca_dev, D_PROBE, "probe=0x%02x\n", probe);
0663             if (probe == 0xff)
0664                 nOV++;
0665         }
0666 
0667         if (nOV) {
0668             gspca_dbg(gspca_dev, D_PROBE, "0xff -> OVXXXX\n");
0669             gspca_dbg(gspca_dev, D_PROBE, "probing for sensor OV2640 or OV9655");
0670 
0671             nb26 = nb96 = 0;
0672             for (ntry = 0; ntry < 4; ntry++) {
0673                 ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
0674                         0, NULL);
0675                 msleep(3);
0676                 ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
0677                         0, NULL);
0678                 msleep(10);
0679 
0680                 /* Wait for 26(OV2640) or 96(OV9655) */
0681                 ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
0682                         1, &probe);
0683 
0684                 if (probe == 0x26 || probe == 0x40) {
0685                     gspca_dbg(gspca_dev, D_PROBE,
0686                           "probe=0x%02x -> OV2640\n",
0687                           probe);
0688                     sd->sensor = ID_OV2640;
0689                     nb26 += 4;
0690                     break;
0691                 }
0692                 if (probe == 0x96 || probe == 0x55) {
0693                     gspca_dbg(gspca_dev, D_PROBE,
0694                           "probe=0x%02x -> OV9655\n",
0695                           probe);
0696                     sd->sensor = ID_OV9655;
0697                     nb96 += 4;
0698                     break;
0699                 }
0700                 gspca_dbg(gspca_dev, D_PROBE, "probe=0x%02x\n",
0701                       probe);
0702                 if (probe == 0x00)
0703                     nb26++;
0704                 if (probe == 0xff)
0705                     nb96++;
0706                 msleep(3);
0707             }
0708             if (nb26 < 4 && nb96 < 4)
0709                 return -1;
0710         } else {
0711             gspca_dbg(gspca_dev, D_PROBE, "Not any 0xff -> MI2020\n");
0712             sd->sensor = ID_MI2020;
0713         }
0714     }
0715 
0716     if (_MI1320_) {
0717         gspca_dbg(gspca_dev, D_PROBE, "05e3:f191 sensor MI1320 (1.3M)\n");
0718     } else if (_MI2020_) {
0719         gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor MI2020 (2.0M)\n");
0720     } else if (_OV9655_) {
0721         gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor OV9655 (1.3M)\n");
0722     } else if (_OV2640_) {
0723         gspca_dbg(gspca_dev, D_PROBE, "05e3:0503 sensor OV2640 (2.0M)\n");
0724     } else {
0725         gspca_dbg(gspca_dev, D_PROBE, "***** Unknown sensor *****\n");
0726         return -1;
0727     }
0728 
0729     return 0;
0730 }