0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #define MODULE_NAME "mars"
0012
0013 #include "gspca.h"
0014 #include "jpeg.h"
0015
0016 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
0017 MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
0018 MODULE_LICENSE("GPL");
0019
0020 #define QUALITY 50
0021
0022
0023 struct sd {
0024 struct gspca_dev gspca_dev;
0025
0026 struct v4l2_ctrl *brightness;
0027 struct v4l2_ctrl *saturation;
0028 struct v4l2_ctrl *sharpness;
0029 struct v4l2_ctrl *gamma;
0030 struct {
0031 struct v4l2_ctrl *illum_top;
0032 struct v4l2_ctrl *illum_bottom;
0033 };
0034 u8 jpeg_hdr[JPEG_HDR_SZ];
0035 };
0036
0037
0038 static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
0039 static void setcolors(struct gspca_dev *gspca_dev, s32 val);
0040 static void setgamma(struct gspca_dev *gspca_dev, s32 val);
0041 static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
0042
0043 static const struct v4l2_pix_format vga_mode[] = {
0044 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0045 .bytesperline = 320,
0046 .sizeimage = 320 * 240 * 3 / 8 + 590,
0047 .colorspace = V4L2_COLORSPACE_JPEG,
0048 .priv = 2},
0049 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0050 .bytesperline = 640,
0051 .sizeimage = 640 * 480 * 3 / 8 + 590,
0052 .colorspace = V4L2_COLORSPACE_JPEG,
0053 .priv = 1},
0054 };
0055
0056 static const __u8 mi_data[0x20] = {
0057
0058 0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
0059
0060 0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
0061
0062 0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
0063
0064 0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
0065 };
0066
0067
0068 static void reg_w(struct gspca_dev *gspca_dev,
0069 int len)
0070 {
0071 int alen, ret;
0072
0073 if (gspca_dev->usb_err < 0)
0074 return;
0075
0076 ret = usb_bulk_msg(gspca_dev->dev,
0077 usb_sndbulkpipe(gspca_dev->dev, 4),
0078 gspca_dev->usb_buf,
0079 len,
0080 &alen,
0081 500);
0082 if (ret < 0) {
0083 pr_err("reg write [%02x] error %d\n",
0084 gspca_dev->usb_buf[0], ret);
0085 gspca_dev->usb_err = ret;
0086 }
0087 }
0088
0089 static void mi_w(struct gspca_dev *gspca_dev,
0090 u8 addr,
0091 u8 value)
0092 {
0093 gspca_dev->usb_buf[0] = 0x1f;
0094 gspca_dev->usb_buf[1] = 0;
0095 gspca_dev->usb_buf[2] = addr;
0096 gspca_dev->usb_buf[3] = value;
0097
0098 reg_w(gspca_dev, 4);
0099 }
0100
0101 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
0102 {
0103 gspca_dev->usb_buf[0] = 0x61;
0104 gspca_dev->usb_buf[1] = val;
0105 reg_w(gspca_dev, 2);
0106 }
0107
0108 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
0109 {
0110 gspca_dev->usb_buf[0] = 0x5f;
0111 gspca_dev->usb_buf[1] = val << 3;
0112 gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
0113 reg_w(gspca_dev, 3);
0114 }
0115
0116 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
0117 {
0118 gspca_dev->usb_buf[0] = 0x06;
0119 gspca_dev->usb_buf[1] = val * 0x40;
0120 reg_w(gspca_dev, 2);
0121 }
0122
0123 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
0124 {
0125 gspca_dev->usb_buf[0] = 0x67;
0126 gspca_dev->usb_buf[1] = val * 4 + 3;
0127 reg_w(gspca_dev, 2);
0128 }
0129
0130 static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
0131 {
0132
0133 gspca_dev->usb_buf[0] = 0x22;
0134 if (top)
0135 gspca_dev->usb_buf[1] = 0x76;
0136 else if (bottom)
0137 gspca_dev->usb_buf[1] = 0x7a;
0138 else
0139 gspca_dev->usb_buf[1] = 0x7e;
0140 reg_w(gspca_dev, 2);
0141 }
0142
0143 static int mars_s_ctrl(struct v4l2_ctrl *ctrl)
0144 {
0145 struct gspca_dev *gspca_dev =
0146 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0147 struct sd *sd = (struct sd *)gspca_dev;
0148
0149 gspca_dev->usb_err = 0;
0150
0151 if (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
0152
0153 if (ctrl->is_new && ctrl->val)
0154 sd->illum_bottom->val = 0;
0155 if (sd->illum_bottom->is_new && sd->illum_bottom->val)
0156 sd->illum_top->val = 0;
0157 }
0158
0159 if (!gspca_dev->streaming)
0160 return 0;
0161
0162 switch (ctrl->id) {
0163 case V4L2_CID_BRIGHTNESS:
0164 setbrightness(gspca_dev, ctrl->val);
0165 break;
0166 case V4L2_CID_SATURATION:
0167 setcolors(gspca_dev, ctrl->val);
0168 break;
0169 case V4L2_CID_GAMMA:
0170 setgamma(gspca_dev, ctrl->val);
0171 break;
0172 case V4L2_CID_ILLUMINATORS_1:
0173 setilluminators(gspca_dev, sd->illum_top->val,
0174 sd->illum_bottom->val);
0175 break;
0176 case V4L2_CID_SHARPNESS:
0177 setsharpness(gspca_dev, ctrl->val);
0178 break;
0179 default:
0180 return -EINVAL;
0181 }
0182 return gspca_dev->usb_err;
0183 }
0184
0185 static const struct v4l2_ctrl_ops mars_ctrl_ops = {
0186 .s_ctrl = mars_s_ctrl,
0187 };
0188
0189
0190 static int sd_init_controls(struct gspca_dev *gspca_dev)
0191 {
0192 struct sd *sd = (struct sd *) gspca_dev;
0193 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0194
0195 gspca_dev->vdev.ctrl_handler = hdl;
0196 v4l2_ctrl_handler_init(hdl, 6);
0197 sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0198 V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
0199 sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0200 V4L2_CID_SATURATION, 0, 255, 1, 200);
0201 sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0202 V4L2_CID_GAMMA, 0, 3, 1, 1);
0203 sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0204 V4L2_CID_SHARPNESS, 0, 2, 1, 1);
0205 sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0206 V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
0207 sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
0208 sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
0209 V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
0210 sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
0211 if (hdl->error) {
0212 pr_err("Could not initialize controls\n");
0213 return hdl->error;
0214 }
0215 v4l2_ctrl_cluster(2, &sd->illum_top);
0216 return 0;
0217 }
0218
0219
0220 static int sd_config(struct gspca_dev *gspca_dev,
0221 const struct usb_device_id *id)
0222 {
0223 struct cam *cam;
0224
0225 cam = &gspca_dev->cam;
0226 cam->cam_mode = vga_mode;
0227 cam->nmodes = ARRAY_SIZE(vga_mode);
0228 return 0;
0229 }
0230
0231
0232 static int sd_init(struct gspca_dev *gspca_dev)
0233 {
0234 return 0;
0235 }
0236
0237 static int sd_start(struct gspca_dev *gspca_dev)
0238 {
0239 struct sd *sd = (struct sd *) gspca_dev;
0240 u8 *data;
0241 int i;
0242
0243
0244 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
0245 gspca_dev->pixfmt.width,
0246 0x21);
0247 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
0248
0249 data = gspca_dev->usb_buf;
0250
0251 data[0] = 0x01;
0252 data[1] = 0x01;
0253 reg_w(gspca_dev, 2);
0254
0255
0256
0257
0258 data[0] = 0x00;
0259 data[1] = 0x0c | 0x01;
0260 data[2] = 0x01;
0261 data[3] = gspca_dev->pixfmt.width / 8;
0262 data[4] = gspca_dev->pixfmt.height / 8;
0263 data[5] = 0x30;
0264
0265 data[6] = 0x02;
0266 data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;
0267 data[8] = 0x01;
0268
0269
0270
0271 data[9] = 0x52;
0272
0273 data[10] = 0x18;
0274
0275 reg_w(gspca_dev, 11);
0276
0277 data[0] = 0x23;
0278 data[1] = 0x09;
0279
0280 reg_w(gspca_dev, 2);
0281
0282 data[0] = 0x3c;
0283
0284
0285
0286
0287 data[1] = 50;
0288
0289 reg_w(gspca_dev, 2);
0290
0291
0292 data[0] = 0x5e;
0293 data[1] = 0;
0294
0295
0296
0297
0298 data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
0299 data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
0300 data[4] = v4l2_ctrl_g_ctrl(sd->brightness);
0301 data[5] = 0x00;
0302
0303 reg_w(gspca_dev, 6);
0304
0305 data[0] = 0x67;
0306
0307 data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
0308 data[2] = 0x14;
0309 reg_w(gspca_dev, 3);
0310
0311 data[0] = 0x69;
0312 data[1] = 0x2f;
0313 data[2] = 0x28;
0314 data[3] = 0x42;
0315 reg_w(gspca_dev, 4);
0316
0317 data[0] = 0x63;
0318 data[1] = 0x07;
0319 reg_w(gspca_dev, 2);
0320
0321
0322
0323 for (i = 0; i < sizeof mi_data; i++)
0324 mi_w(gspca_dev, i + 1, mi_data[i]);
0325
0326 data[0] = 0x00;
0327 data[1] = 0x4d;
0328 reg_w(gspca_dev, 2);
0329
0330 setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
0331 v4l2_ctrl_g_ctrl(sd->illum_bottom));
0332
0333 return gspca_dev->usb_err;
0334 }
0335
0336 static void sd_stopN(struct gspca_dev *gspca_dev)
0337 {
0338 struct sd *sd = (struct sd *) gspca_dev;
0339
0340 if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
0341 v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
0342 setilluminators(gspca_dev, false, false);
0343 msleep(20);
0344 }
0345
0346 gspca_dev->usb_buf[0] = 1;
0347 gspca_dev->usb_buf[1] = 0;
0348 reg_w(gspca_dev, 2);
0349 }
0350
0351 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0352 u8 *data,
0353 int len)
0354 {
0355 struct sd *sd = (struct sd *) gspca_dev;
0356 int p;
0357
0358 if (len < 6) {
0359
0360 return;
0361 }
0362 for (p = 0; p < len - 6; p++) {
0363 if (data[0 + p] == 0xff
0364 && data[1 + p] == 0xff
0365 && data[2 + p] == 0x00
0366 && data[3 + p] == 0xff
0367 && data[4 + p] == 0x96) {
0368 if (data[5 + p] == 0x64
0369 || data[5 + p] == 0x65
0370 || data[5 + p] == 0x66
0371 || data[5 + p] == 0x67) {
0372 gspca_dbg(gspca_dev, D_PACK, "sof offset: %d len: %d\n",
0373 p, len);
0374 gspca_frame_add(gspca_dev, LAST_PACKET,
0375 data, p);
0376
0377
0378 gspca_frame_add(gspca_dev, FIRST_PACKET,
0379 sd->jpeg_hdr, JPEG_HDR_SZ);
0380 data += p + 16;
0381 len -= p + 16;
0382 break;
0383 }
0384 }
0385 }
0386 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0387 }
0388
0389
0390 static const struct sd_desc sd_desc = {
0391 .name = MODULE_NAME,
0392 .config = sd_config,
0393 .init = sd_init,
0394 .init_controls = sd_init_controls,
0395 .start = sd_start,
0396 .stopN = sd_stopN,
0397 .pkt_scan = sd_pkt_scan,
0398 };
0399
0400
0401 static const struct usb_device_id device_table[] = {
0402 {USB_DEVICE(0x093a, 0x050f)},
0403 {}
0404 };
0405 MODULE_DEVICE_TABLE(usb, device_table);
0406
0407
0408 static int sd_probe(struct usb_interface *intf,
0409 const struct usb_device_id *id)
0410 {
0411 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0412 THIS_MODULE);
0413 }
0414
0415 static struct usb_driver sd_driver = {
0416 .name = MODULE_NAME,
0417 .id_table = device_table,
0418 .probe = sd_probe,
0419 .disconnect = gspca_disconnect,
0420 #ifdef CONFIG_PM
0421 .suspend = gspca_suspend,
0422 .resume = gspca_resume,
0423 .reset_resume = gspca_resume,
0424 #endif
0425 };
0426
0427 module_usb_driver(sd_driver);