0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #define MODULE_NAME "spca1528"
0011
0012 #include "gspca.h"
0013 #include "jpeg.h"
0014
0015 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
0016 MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
0017 MODULE_LICENSE("GPL");
0018
0019
0020 struct sd {
0021 struct gspca_dev gspca_dev;
0022
0023 u8 pkt_seq;
0024
0025 u8 jpeg_hdr[JPEG_HDR_SZ];
0026 };
0027
0028 static const struct v4l2_pix_format vga_mode[] = {
0029
0030
0031
0032
0033
0034
0035
0036 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0037 .bytesperline = 320,
0038 .sizeimage = 320 * 240 * 4 / 8 + 590,
0039 .colorspace = V4L2_COLORSPACE_JPEG,
0040 .priv = 2},
0041 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0042 .bytesperline = 640,
0043 .sizeimage = 640 * 480 * 3 / 8 + 590,
0044 .colorspace = V4L2_COLORSPACE_JPEG,
0045 .priv = 1},
0046 };
0047
0048
0049 static void reg_r(struct gspca_dev *gspca_dev,
0050 u8 req,
0051 u16 index,
0052 int len)
0053 {
0054 #if USB_BUF_SZ < 64
0055 #error "USB buffer too small"
0056 #endif
0057 struct usb_device *dev = gspca_dev->dev;
0058 int ret;
0059
0060 if (gspca_dev->usb_err < 0)
0061 return;
0062 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
0063 req,
0064 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0065 0x0000,
0066 index,
0067 gspca_dev->usb_buf, len,
0068 500);
0069 gspca_dbg(gspca_dev, D_USBI, "GET %02x 0000 %04x %02x\n", req, index,
0070 gspca_dev->usb_buf[0]);
0071 if (ret < 0) {
0072 pr_err("reg_r err %d\n", ret);
0073 gspca_dev->usb_err = ret;
0074
0075
0076
0077
0078 memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
0079 }
0080 }
0081
0082 static void reg_w(struct gspca_dev *gspca_dev,
0083 u8 req,
0084 u16 value,
0085 u16 index)
0086 {
0087 struct usb_device *dev = gspca_dev->dev;
0088 int ret;
0089
0090 if (gspca_dev->usb_err < 0)
0091 return;
0092 gspca_dbg(gspca_dev, D_USBO, "SET %02x %04x %04x\n", req, value, index);
0093 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
0094 req,
0095 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0096 value, index,
0097 NULL, 0, 500);
0098 if (ret < 0) {
0099 pr_err("reg_w err %d\n", ret);
0100 gspca_dev->usb_err = ret;
0101 }
0102 }
0103
0104 static void reg_wb(struct gspca_dev *gspca_dev,
0105 u8 req,
0106 u16 value,
0107 u16 index,
0108 u8 byte)
0109 {
0110 struct usb_device *dev = gspca_dev->dev;
0111 int ret;
0112
0113 if (gspca_dev->usb_err < 0)
0114 return;
0115 gspca_dbg(gspca_dev, D_USBO, "SET %02x %04x %04x %02x\n",
0116 req, value, index, byte);
0117 gspca_dev->usb_buf[0] = byte;
0118 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
0119 req,
0120 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0121 value, index,
0122 gspca_dev->usb_buf, 1, 500);
0123 if (ret < 0) {
0124 pr_err("reg_w err %d\n", ret);
0125 gspca_dev->usb_err = ret;
0126 }
0127 }
0128
0129 static void wait_status_0(struct gspca_dev *gspca_dev)
0130 {
0131 int i, w;
0132
0133 i = 16;
0134 w = 0;
0135 do {
0136 reg_r(gspca_dev, 0x21, 0x0000, 1);
0137 if (gspca_dev->usb_buf[0] == 0)
0138 return;
0139 w += 15;
0140 msleep(w);
0141 } while (--i > 0);
0142 gspca_err(gspca_dev, "wait_status_0 timeout\n");
0143 gspca_dev->usb_err = -ETIME;
0144 }
0145
0146 static void wait_status_1(struct gspca_dev *gspca_dev)
0147 {
0148 int i;
0149
0150 i = 10;
0151 do {
0152 reg_r(gspca_dev, 0x21, 0x0001, 1);
0153 msleep(10);
0154 if (gspca_dev->usb_buf[0] == 1) {
0155 reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
0156 reg_r(gspca_dev, 0x21, 0x0001, 1);
0157 return;
0158 }
0159 } while (--i > 0);
0160 gspca_err(gspca_dev, "wait_status_1 timeout\n");
0161 gspca_dev->usb_err = -ETIME;
0162 }
0163
0164 static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
0165 {
0166 reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val);
0167 }
0168
0169 static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
0170 {
0171 reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val);
0172 }
0173
0174 static void sethue(struct gspca_dev *gspca_dev, s32 val)
0175 {
0176 reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val);
0177 }
0178
0179 static void setcolor(struct gspca_dev *gspca_dev, s32 val)
0180 {
0181 reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val);
0182 }
0183
0184 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
0185 {
0186 reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val);
0187 }
0188
0189
0190 static int sd_config(struct gspca_dev *gspca_dev,
0191 const struct usb_device_id *id)
0192 {
0193 gspca_dev->cam.cam_mode = vga_mode;
0194 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
0195 gspca_dev->cam.npkt = 128;
0196
0197
0198 return 0;
0199 }
0200
0201
0202 static int sd_init(struct gspca_dev *gspca_dev)
0203 {
0204 reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
0205 reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
0206 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
0207 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
0208 msleep(8);
0209 reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
0210 reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
0211 reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
0212
0213 reg_r(gspca_dev, 0x20, 0x0000, 1);
0214 reg_r(gspca_dev, 0x20, 0x0000, 5);
0215 reg_r(gspca_dev, 0x23, 0x0000, 64);
0216 gspca_dbg(gspca_dev, D_PROBE, "%s%s\n", &gspca_dev->usb_buf[0x1c],
0217 &gspca_dev->usb_buf[0x30]);
0218 reg_r(gspca_dev, 0x23, 0x0001, 64);
0219 return gspca_dev->usb_err;
0220 }
0221
0222
0223 static int sd_isoc_init(struct gspca_dev *gspca_dev)
0224 {
0225 u8 mode;
0226
0227 reg_r(gspca_dev, 0x00, 0x2520, 1);
0228 wait_status_0(gspca_dev);
0229 reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
0230 wait_status_1(gspca_dev);
0231
0232 wait_status_0(gspca_dev);
0233 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
0234 reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
0235 reg_r(gspca_dev, 0x25, 0x0004, 1);
0236 reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);
0237 reg_r(gspca_dev, 0x27, 0x0000, 1);
0238
0239
0240
0241
0242 return gspca_dev->usb_err;
0243 }
0244
0245
0246 static int sd_start(struct gspca_dev *gspca_dev)
0247 {
0248 struct sd *sd = (struct sd *) gspca_dev;
0249
0250
0251 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
0252 gspca_dev->pixfmt.width,
0253 0x22);
0254
0255
0256 jpeg_set_qual(sd->jpeg_hdr, 85);
0257
0258 reg_r(gspca_dev, 0x00, 0x2520, 1);
0259 msleep(8);
0260
0261
0262 wait_status_0(gspca_dev);
0263 reg_w(gspca_dev, 0x31, 0x0000, 0x0004);
0264 wait_status_1(gspca_dev);
0265 wait_status_0(gspca_dev);
0266 msleep(200);
0267
0268 sd->pkt_seq = 0;
0269 return gspca_dev->usb_err;
0270 }
0271
0272 static void sd_stopN(struct gspca_dev *gspca_dev)
0273 {
0274
0275 wait_status_0(gspca_dev);
0276 reg_w(gspca_dev, 0x31, 0x0000, 0x0000);
0277 wait_status_1(gspca_dev);
0278 wait_status_0(gspca_dev);
0279 }
0280
0281
0282 static void add_packet(struct gspca_dev *gspca_dev,
0283 u8 *data,
0284 int len)
0285 {
0286 int i;
0287
0288 i = 0;
0289 do {
0290 if (data[i] == 0xff) {
0291 gspca_frame_add(gspca_dev, INTER_PACKET,
0292 data, i + 1);
0293 len -= i;
0294 data += i;
0295 *data = 0x00;
0296 i = 0;
0297 }
0298 } while (++i < len);
0299 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0300 }
0301
0302 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0303 u8 *data,
0304 int len)
0305 {
0306 struct sd *sd = (struct sd *) gspca_dev;
0307 static const u8 ffd9[] = {0xff, 0xd9};
0308
0309
0310
0311
0312
0313
0314
0315 if (len < 3)
0316 return;
0317 if (*data == 0x02) {
0318 if (data[1] & 0x02) {
0319 sd->pkt_seq = !(data[1] & 1);
0320 add_packet(gspca_dev, data + 2, len - 2);
0321 gspca_frame_add(gspca_dev, LAST_PACKET,
0322 ffd9, 2);
0323 return;
0324 }
0325 if ((data[1] & 1) != sd->pkt_seq)
0326 goto err;
0327 if (gspca_dev->last_packet_type == LAST_PACKET)
0328 gspca_frame_add(gspca_dev, FIRST_PACKET,
0329 sd->jpeg_hdr, JPEG_HDR_SZ);
0330 add_packet(gspca_dev, data + 2, len - 2);
0331 return;
0332 }
0333 err:
0334 gspca_dev->last_packet_type = DISCARD_PACKET;
0335 }
0336
0337 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0338 {
0339 struct gspca_dev *gspca_dev =
0340 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0341
0342 gspca_dev->usb_err = 0;
0343
0344 if (!gspca_dev->streaming)
0345 return 0;
0346
0347 switch (ctrl->id) {
0348 case V4L2_CID_BRIGHTNESS:
0349 setbrightness(gspca_dev, ctrl->val);
0350 break;
0351 case V4L2_CID_CONTRAST:
0352 setcontrast(gspca_dev, ctrl->val);
0353 break;
0354 case V4L2_CID_HUE:
0355 sethue(gspca_dev, ctrl->val);
0356 break;
0357 case V4L2_CID_SATURATION:
0358 setcolor(gspca_dev, ctrl->val);
0359 break;
0360 case V4L2_CID_SHARPNESS:
0361 setsharpness(gspca_dev, ctrl->val);
0362 break;
0363 }
0364 return gspca_dev->usb_err;
0365 }
0366
0367 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0368 .s_ctrl = sd_s_ctrl,
0369 };
0370
0371 static int sd_init_controls(struct gspca_dev *gspca_dev)
0372 {
0373 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0374
0375 gspca_dev->vdev.ctrl_handler = hdl;
0376 v4l2_ctrl_handler_init(hdl, 5);
0377 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0378 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
0379 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0380 V4L2_CID_CONTRAST, 0, 8, 1, 1);
0381 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0382 V4L2_CID_HUE, 0, 255, 1, 0);
0383 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0384 V4L2_CID_SATURATION, 0, 8, 1, 1);
0385 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0386 V4L2_CID_SHARPNESS, 0, 255, 1, 0);
0387
0388 if (hdl->error) {
0389 pr_err("Could not initialize controls\n");
0390 return hdl->error;
0391 }
0392 return 0;
0393 }
0394
0395
0396 static const struct sd_desc sd_desc = {
0397 .name = MODULE_NAME,
0398 .config = sd_config,
0399 .init = sd_init,
0400 .init_controls = sd_init_controls,
0401 .isoc_init = sd_isoc_init,
0402 .start = sd_start,
0403 .stopN = sd_stopN,
0404 .pkt_scan = sd_pkt_scan,
0405 };
0406
0407
0408 static const struct usb_device_id device_table[] = {
0409 {USB_DEVICE(0x04fc, 0x1528)},
0410 {}
0411 };
0412 MODULE_DEVICE_TABLE(usb, device_table);
0413
0414
0415 static int sd_probe(struct usb_interface *intf,
0416 const struct usb_device_id *id)
0417 {
0418
0419 if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
0420 return -ENODEV;
0421
0422 return gspca_dev_probe2(intf, id, &sd_desc, sizeof(struct sd),
0423 THIS_MODULE);
0424 }
0425
0426 static struct usb_driver sd_driver = {
0427 .name = MODULE_NAME,
0428 .id_table = device_table,
0429 .probe = sd_probe,
0430 .disconnect = gspca_disconnect,
0431 #ifdef CONFIG_PM
0432 .suspend = gspca_suspend,
0433 .resume = gspca_resume,
0434 .reset_resume = gspca_resume,
0435 #endif
0436 };
0437
0438 module_usb_driver(sd_driver);