stk014.c revision 9a731a3265a808c806766a28e2b62e9da78f9ac6
1/* 2 * Syntek DV4000 (STK014) subdriver 3 * 4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#define MODULE_NAME "stk014" 22 23#include "gspca.h" 24#include "jpeg.h" 25 26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 27MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); 28MODULE_LICENSE("GPL"); 29 30/* specific webcam descriptor */ 31struct sd { 32 struct gspca_dev gspca_dev; /* !! must be the first item */ 33 34 unsigned char brightness; 35 unsigned char contrast; 36 unsigned char colors; 37 unsigned char lightfreq; 38 u8 quality; 39#define QUALITY_MIN 60 40#define QUALITY_MAX 95 41#define QUALITY_DEF 80 42 43 u8 jpeg_hdr[JPEG_HDR_SZ]; 44}; 45 46/* V4L2 controls supported by the driver */ 47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 53static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); 54static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); 55 56static const struct ctrl sd_ctrls[] = { 57 { 58 { 59 .id = V4L2_CID_BRIGHTNESS, 60 .type = V4L2_CTRL_TYPE_INTEGER, 61 .name = "Brightness", 62 .minimum = 0, 63 .maximum = 255, 64 .step = 1, 65#define BRIGHTNESS_DEF 127 66 .default_value = BRIGHTNESS_DEF, 67 }, 68 .set = sd_setbrightness, 69 .get = sd_getbrightness, 70 }, 71 { 72 { 73 .id = V4L2_CID_CONTRAST, 74 .type = V4L2_CTRL_TYPE_INTEGER, 75 .name = "Contrast", 76 .minimum = 0, 77 .maximum = 255, 78 .step = 1, 79#define CONTRAST_DEF 127 80 .default_value = CONTRAST_DEF, 81 }, 82 .set = sd_setcontrast, 83 .get = sd_getcontrast, 84 }, 85 { 86 { 87 .id = V4L2_CID_SATURATION, 88 .type = V4L2_CTRL_TYPE_INTEGER, 89 .name = "Color", 90 .minimum = 0, 91 .maximum = 255, 92 .step = 1, 93#define COLOR_DEF 127 94 .default_value = COLOR_DEF, 95 }, 96 .set = sd_setcolors, 97 .get = sd_getcolors, 98 }, 99 { 100 { 101 .id = V4L2_CID_POWER_LINE_FREQUENCY, 102 .type = V4L2_CTRL_TYPE_MENU, 103 .name = "Light frequency filter", 104 .minimum = 1, 105 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ 106 .step = 1, 107#define FREQ_DEF 1 108 .default_value = FREQ_DEF, 109 }, 110 .set = sd_setfreq, 111 .get = sd_getfreq, 112 }, 113}; 114 115static const struct v4l2_pix_format vga_mode[] = { 116 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 117 .bytesperline = 320, 118 .sizeimage = 320 * 240 * 3 / 8 + 590, 119 .colorspace = V4L2_COLORSPACE_JPEG, 120 .priv = 1}, 121 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 122 .bytesperline = 640, 123 .sizeimage = 640 * 480 * 3 / 8 + 590, 124 .colorspace = V4L2_COLORSPACE_JPEG, 125 .priv = 0}, 126}; 127 128/* -- read a register -- */ 129static u8 reg_r(struct gspca_dev *gspca_dev, 130 __u16 index) 131{ 132 struct usb_device *dev = gspca_dev->dev; 133 int ret; 134 135 if (gspca_dev->usb_err < 0) 136 return 0; 137 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 138 0x00, 139 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 140 0x00, 141 index, 142 gspca_dev->usb_buf, 1, 143 500); 144 if (ret < 0) { 145 PDEBUG(D_ERR, "reg_r err %d", ret); 146 gspca_dev->usb_err = ret; 147 return 0; 148 } 149 return gspca_dev->usb_buf[0]; 150} 151 152/* -- write a register -- */ 153static void reg_w(struct gspca_dev *gspca_dev, 154 __u16 index, __u16 value) 155{ 156 struct usb_device *dev = gspca_dev->dev; 157 int ret; 158 159 if (gspca_dev->usb_err < 0) 160 return; 161 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 162 0x01, 163 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 164 value, 165 index, 166 NULL, 167 0, 168 500); 169 if (ret < 0) { 170 PDEBUG(D_ERR, "reg_w err %d", ret); 171 gspca_dev->usb_err = ret; 172 } 173} 174 175/* -- get a bulk value (4 bytes) -- */ 176static void rcv_val(struct gspca_dev *gspca_dev, 177 int ads) 178{ 179 struct usb_device *dev = gspca_dev->dev; 180 int alen, ret; 181 182 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff); 183 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff); 184 reg_w(gspca_dev, 0x636, ads & 0xff); 185 reg_w(gspca_dev, 0x637, 0); 186 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */ 187 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */ 188 reg_w(gspca_dev, 0x63a, 0); 189 reg_w(gspca_dev, 0x63b, 0); 190 reg_w(gspca_dev, 0x630, 5); 191 if (gspca_dev->usb_err < 0) 192 return; 193 ret = usb_bulk_msg(dev, 194 usb_rcvbulkpipe(dev, 0x05), 195 gspca_dev->usb_buf, 196 4, /* length */ 197 &alen, 198 500); /* timeout in milliseconds */ 199 if (ret < 0) { 200 PDEBUG(D_ERR, "rcv_val err %d", ret); 201 gspca_dev->usb_err = ret; 202 } 203} 204 205/* -- send a bulk value -- */ 206static void snd_val(struct gspca_dev *gspca_dev, 207 int ads, 208 unsigned int val) 209{ 210 struct usb_device *dev = gspca_dev->dev; 211 int alen, ret; 212 __u8 seq = 0; 213 214 if (ads == 0x003f08) { 215 reg_r(gspca_dev, 0x0704); 216 seq = reg_r(gspca_dev, 0x0705); 217 reg_r(gspca_dev, 0x0650); 218 reg_w(gspca_dev, 0x654, seq); 219 } else { 220 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); 221 } 222 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff); 223 reg_w(gspca_dev, 0x656, ads & 0xff); 224 reg_w(gspca_dev, 0x657, 0); 225 reg_w(gspca_dev, 0x658, 0x04); /* size */ 226 reg_w(gspca_dev, 0x659, 0); 227 reg_w(gspca_dev, 0x65a, 0); 228 reg_w(gspca_dev, 0x65b, 0); 229 reg_w(gspca_dev, 0x650, 5); 230 if (gspca_dev->usb_err < 0) 231 return; 232 gspca_dev->usb_buf[0] = val >> 24; 233 gspca_dev->usb_buf[1] = val >> 16; 234 gspca_dev->usb_buf[2] = val >> 8; 235 gspca_dev->usb_buf[3] = val; 236 ret = usb_bulk_msg(dev, 237 usb_sndbulkpipe(dev, 6), 238 gspca_dev->usb_buf, 239 4, 240 &alen, 241 500); /* timeout in milliseconds */ 242 if (ret < 0) { 243 PDEBUG(D_ERR, "snd_val err %d", ret); 244 gspca_dev->usb_err = ret; 245 } else { 246 if (ads == 0x003f08) { 247 seq += 4; 248 seq &= 0x3f; 249 reg_w(gspca_dev, 0x705, seq); 250 } 251 } 252} 253 254/* set a camera parameter */ 255static void set_par(struct gspca_dev *gspca_dev, 256 int parval) 257{ 258 snd_val(gspca_dev, 0x003f08, parval); 259} 260 261static void setbrightness(struct gspca_dev *gspca_dev) 262{ 263 struct sd *sd = (struct sd *) gspca_dev; 264 int parval; 265 266 parval = 0x06000000 /* whiteness */ 267 + (sd->brightness << 16); 268 set_par(gspca_dev, parval); 269} 270 271static void setcontrast(struct gspca_dev *gspca_dev) 272{ 273 struct sd *sd = (struct sd *) gspca_dev; 274 int parval; 275 276 parval = 0x07000000 /* contrast */ 277 + (sd->contrast << 16); 278 set_par(gspca_dev, parval); 279} 280 281static void setcolors(struct gspca_dev *gspca_dev) 282{ 283 struct sd *sd = (struct sd *) gspca_dev; 284 int parval; 285 286 parval = 0x08000000 /* saturation */ 287 + (sd->colors << 16); 288 set_par(gspca_dev, parval); 289} 290 291static void setfreq(struct gspca_dev *gspca_dev) 292{ 293 struct sd *sd = (struct sd *) gspca_dev; 294 295 set_par(gspca_dev, sd->lightfreq == 1 296 ? 0x33640000 /* 50 Hz */ 297 : 0x33780000); /* 60 Hz */ 298} 299 300/* this function is called at probe time */ 301static int sd_config(struct gspca_dev *gspca_dev, 302 const struct usb_device_id *id) 303{ 304 struct sd *sd = (struct sd *) gspca_dev; 305 306 gspca_dev->cam.cam_mode = vga_mode; 307 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); 308 sd->brightness = BRIGHTNESS_DEF; 309 sd->contrast = CONTRAST_DEF; 310 sd->colors = COLOR_DEF; 311 sd->lightfreq = FREQ_DEF; 312 sd->quality = QUALITY_DEF; 313 return 0; 314} 315 316/* this function is called at probe and resume time */ 317static int sd_init(struct gspca_dev *gspca_dev) 318{ 319 u8 ret; 320 321 /* check if the device responds */ 322 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 323 ret = reg_r(gspca_dev, 0x0740); 324 if (gspca_dev->usb_err >= 0) { 325 if (ret != 0xff) { 326 PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret); 327 gspca_dev->usb_err = -EIO; 328 } 329 } 330 return gspca_dev->usb_err; 331} 332 333/* -- start the camera -- */ 334static int sd_start(struct gspca_dev *gspca_dev) 335{ 336 struct sd *sd = (struct sd *) gspca_dev; 337 int ret, value; 338 339 /* create the JPEG header */ 340 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 341 0x22); /* JPEG 411 */ 342 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 343 344 /* work on alternate 1 */ 345 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 346 347 set_par(gspca_dev, 0x10000000); 348 set_par(gspca_dev, 0x00000000); 349 set_par(gspca_dev, 0x8002e001); 350 set_par(gspca_dev, 0x14000000); 351 if (gspca_dev->width > 320) 352 value = 0x8002e001; /* 640x480 */ 353 else 354 value = 0x4001f000; /* 320x240 */ 355 set_par(gspca_dev, value); 356 ret = usb_set_interface(gspca_dev->dev, 357 gspca_dev->iface, 358 gspca_dev->alt); 359 if (ret < 0) { 360 PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed", 361 gspca_dev->iface, gspca_dev->alt); 362 gspca_dev->usb_err = ret; 363 goto out; 364 } 365 reg_r(gspca_dev, 0x0630); 366 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ 367 reg_r(gspca_dev, 0x0650); 368 snd_val(gspca_dev, 0x000020, 0xffffffff); 369 reg_w(gspca_dev, 0x0620, 0); 370 reg_w(gspca_dev, 0x0630, 0); 371 reg_w(gspca_dev, 0x0640, 0); 372 reg_w(gspca_dev, 0x0650, 0); 373 reg_w(gspca_dev, 0x0660, 0); 374 setbrightness(gspca_dev); /* whiteness */ 375 setcontrast(gspca_dev); /* contrast */ 376 setcolors(gspca_dev); /* saturation */ 377 set_par(gspca_dev, 0x09800000); /* Red ? */ 378 set_par(gspca_dev, 0x0a800000); /* Green ? */ 379 set_par(gspca_dev, 0x0b800000); /* Blue ? */ 380 set_par(gspca_dev, 0x0d030000); /* Gamma ? */ 381 setfreq(gspca_dev); /* light frequency */ 382 383 /* start the video flow */ 384 set_par(gspca_dev, 0x01000000); 385 set_par(gspca_dev, 0x01000000); 386 if (gspca_dev->usb_err >= 0) 387 PDEBUG(D_STREAM, "camera started alt: 0x%02x", 388 gspca_dev->alt); 389out: 390 return gspca_dev->usb_err; 391} 392 393static void sd_stopN(struct gspca_dev *gspca_dev) 394{ 395 struct usb_device *dev = gspca_dev->dev; 396 397 set_par(gspca_dev, 0x02000000); 398 set_par(gspca_dev, 0x02000000); 399 usb_set_interface(dev, gspca_dev->iface, 1); 400 reg_r(gspca_dev, 0x0630); 401 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ 402 reg_r(gspca_dev, 0x0650); 403 snd_val(gspca_dev, 0x000020, 0xffffffff); 404 reg_w(gspca_dev, 0x0620, 0); 405 reg_w(gspca_dev, 0x0630, 0); 406 reg_w(gspca_dev, 0x0640, 0); 407 reg_w(gspca_dev, 0x0650, 0); 408 reg_w(gspca_dev, 0x0660, 0); 409 PDEBUG(D_STREAM, "camera stopped"); 410} 411 412static void sd_pkt_scan(struct gspca_dev *gspca_dev, 413 u8 *data, /* isoc packet */ 414 int len) /* iso packet length */ 415{ 416 struct sd *sd = (struct sd *) gspca_dev; 417 static unsigned char ffd9[] = {0xff, 0xd9}; 418 419 /* a frame starts with: 420 * - 0xff 0xfe 421 * - 0x08 0x00 - length (little endian ?!) 422 * - 4 bytes = size of whole frame (BE - including header) 423 * - 0x00 0x0c 424 * - 0xff 0xd8 425 * - .. JPEG image with escape sequences (ff 00) 426 * (without ending - ff d9) 427 */ 428 if (data[0] == 0xff && data[1] == 0xfe) { 429 gspca_frame_add(gspca_dev, LAST_PACKET, 430 ffd9, 2); 431 432 /* put the JPEG 411 header */ 433 gspca_frame_add(gspca_dev, FIRST_PACKET, 434 sd->jpeg_hdr, JPEG_HDR_SZ); 435 436 /* beginning of the frame */ 437#define STKHDRSZ 12 438 data += STKHDRSZ; 439 len -= STKHDRSZ; 440 } 441 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 442} 443 444static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 445{ 446 struct sd *sd = (struct sd *) gspca_dev; 447 448 sd->brightness = val; 449 if (gspca_dev->streaming) 450 setbrightness(gspca_dev); 451 return gspca_dev->usb_err; 452} 453 454static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 455{ 456 struct sd *sd = (struct sd *) gspca_dev; 457 458 *val = sd->brightness; 459 return 0; 460} 461 462static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 463{ 464 struct sd *sd = (struct sd *) gspca_dev; 465 466 sd->contrast = val; 467 if (gspca_dev->streaming) 468 setcontrast(gspca_dev); 469 return gspca_dev->usb_err; 470} 471 472static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 473{ 474 struct sd *sd = (struct sd *) gspca_dev; 475 476 *val = sd->contrast; 477 return 0; 478} 479 480static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 481{ 482 struct sd *sd = (struct sd *) gspca_dev; 483 484 sd->colors = val; 485 if (gspca_dev->streaming) 486 setcolors(gspca_dev); 487 return gspca_dev->usb_err; 488} 489 490static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 491{ 492 struct sd *sd = (struct sd *) gspca_dev; 493 494 *val = sd->colors; 495 return 0; 496} 497 498static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) 499{ 500 struct sd *sd = (struct sd *) gspca_dev; 501 502 sd->lightfreq = val; 503 if (gspca_dev->streaming) 504 setfreq(gspca_dev); 505 return gspca_dev->usb_err; 506} 507 508static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) 509{ 510 struct sd *sd = (struct sd *) gspca_dev; 511 512 *val = sd->lightfreq; 513 return 0; 514} 515 516static int sd_querymenu(struct gspca_dev *gspca_dev, 517 struct v4l2_querymenu *menu) 518{ 519 switch (menu->id) { 520 case V4L2_CID_POWER_LINE_FREQUENCY: 521 switch (menu->index) { 522 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ 523 strcpy((char *) menu->name, "50 Hz"); 524 return 0; 525 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ 526 strcpy((char *) menu->name, "60 Hz"); 527 return 0; 528 } 529 break; 530 } 531 return -EINVAL; 532} 533 534static int sd_set_jcomp(struct gspca_dev *gspca_dev, 535 struct v4l2_jpegcompression *jcomp) 536{ 537 struct sd *sd = (struct sd *) gspca_dev; 538 539 if (jcomp->quality < QUALITY_MIN) 540 sd->quality = QUALITY_MIN; 541 else if (jcomp->quality > QUALITY_MAX) 542 sd->quality = QUALITY_MAX; 543 else 544 sd->quality = jcomp->quality; 545 if (gspca_dev->streaming) 546 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 547 return gspca_dev->usb_err; 548} 549 550static int sd_get_jcomp(struct gspca_dev *gspca_dev, 551 struct v4l2_jpegcompression *jcomp) 552{ 553 struct sd *sd = (struct sd *) gspca_dev; 554 555 memset(jcomp, 0, sizeof *jcomp); 556 jcomp->quality = sd->quality; 557 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 558 | V4L2_JPEG_MARKER_DQT; 559 return 0; 560} 561 562/* sub-driver description */ 563static const struct sd_desc sd_desc = { 564 .name = MODULE_NAME, 565 .ctrls = sd_ctrls, 566 .nctrls = ARRAY_SIZE(sd_ctrls), 567 .config = sd_config, 568 .init = sd_init, 569 .start = sd_start, 570 .stopN = sd_stopN, 571 .pkt_scan = sd_pkt_scan, 572 .querymenu = sd_querymenu, 573 .get_jcomp = sd_get_jcomp, 574 .set_jcomp = sd_set_jcomp, 575}; 576 577/* -- module initialisation -- */ 578static const __devinitdata struct usb_device_id device_table[] = { 579 {USB_DEVICE(0x05e1, 0x0893)}, 580 {} 581}; 582MODULE_DEVICE_TABLE(usb, device_table); 583 584/* -- device connect -- */ 585static int sd_probe(struct usb_interface *intf, 586 const struct usb_device_id *id) 587{ 588 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 589 THIS_MODULE); 590} 591 592static struct usb_driver sd_driver = { 593 .name = MODULE_NAME, 594 .id_table = device_table, 595 .probe = sd_probe, 596 .disconnect = gspca_disconnect, 597#ifdef CONFIG_PM 598 .suspend = gspca_suspend, 599 .resume = gspca_resume, 600#endif 601}; 602 603/* -- module insert / remove -- */ 604static int __init sd_mod_init(void) 605{ 606 int ret; 607 ret = usb_register(&sd_driver); 608 if (ret < 0) 609 return ret; 610 info("registered"); 611 return 0; 612} 613static void __exit sd_mod_exit(void) 614{ 615 usb_deregister(&sd_driver); 616 info("deregistered"); 617} 618 619module_init(sd_mod_init); 620module_exit(sd_mod_exit); 621