stk014.c revision 4aa0d037a6c8e6b37ecfd986a444f83190c32a21
1/* 2 * Syntek DV4000 (STK014) subdriver 3 * 4 * Copyright (C) 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 22#define MODULE_NAME "stk014" 23 24#include "gspca.h" 25#include "jpeg.h" 26 27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) 28static const char version[] = "0.1.0"; 29 30MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 31MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); 32MODULE_LICENSE("GPL"); 33 34/* specific webcam descriptor */ 35struct sd { 36 struct gspca_dev gspca_dev; /* !! must be the first item */ 37 38 unsigned char brightness; 39 unsigned char contrast; 40 unsigned char colors; 41}; 42 43/* global parameters */ 44static int lightfreq = 50; 45static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */ 46 47/* V4L2 controls supported by the driver */ 48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 52static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 53static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 54 55static struct ctrl sd_ctrls[] = { 56#define SD_BRIGHTNESS 0 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 .default_value = 127, 66 }, 67 .set = sd_setbrightness, 68 .get = sd_getbrightness, 69 }, 70#define SD_CONTRAST 1 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 .default_value = 127, 80 }, 81 .set = sd_setcontrast, 82 .get = sd_getcontrast, 83 }, 84#define SD_COLOR 2 85 { 86 { 87 .id = V4L2_CID_SATURATION, 88 .type = V4L2_CTRL_TYPE_INTEGER, 89 .name = "Saturation", 90 .minimum = 0, 91 .maximum = 255, 92 .step = 1, 93 .default_value = 127, 94 }, 95 .set = sd_setcolors, 96 .get = sd_getcolors, 97 }, 98}; 99 100static struct cam_mode vga_mode[] = { 101 {V4L2_PIX_FMT_JPEG, 320, 240}, 102 {V4L2_PIX_FMT_JPEG, 640, 480}, 103}; 104 105/* -- read a register -- */ 106static int reg_read(struct gspca_dev *gspca_dev, 107 __u16 index, __u8 *buf) 108{ 109 int ret; 110 struct usb_device *dev = gspca_dev->dev; 111 112 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 113 0x00, 114 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 115 0x00, 116 index, 117 buf, 1, 118 500); 119 if (ret < 0) 120 PDEBUG(D_ERR, "reg_read err %d", ret); 121 return ret; 122} 123 124/* -- write a register -- */ 125static int reg_write(struct gspca_dev *gspca_dev, 126 __u16 index, __u16 value) 127{ 128 struct usb_device *dev = gspca_dev->dev; 129 int ret; 130 131 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 132 0x01, 133 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 134 value, 135 index, 136 NULL, 137 0, 138 500); 139 if (ret < 0) 140 PDEBUG(D_ERR, "reg_write err %d", ret); 141 return ret; 142} 143 144/* -- get a value -- */ 145static int rcv_val(struct gspca_dev *gspca_dev, 146 int ads, 147 int len) 148{ 149 struct usb_device *dev = gspca_dev->dev; 150 int alen, ret; 151 unsigned char bulk_buf[4]; 152 153 reg_write(gspca_dev, 0x634, (ads >> 16) & 0xff); 154 reg_write(gspca_dev, 0x635, (ads >> 8) & 0xff); 155 reg_write(gspca_dev, 0x636, ads & 0xff); 156 reg_write(gspca_dev, 0x637, 0); 157 reg_write(gspca_dev, 0x638, len & 0xff); 158 reg_write(gspca_dev, 0x639, len >> 8); 159 reg_write(gspca_dev, 0x63a, 0); 160 reg_write(gspca_dev, 0x63b, 0); 161 reg_write(gspca_dev, 0x630, 5); 162 if (len > sizeof bulk_buf) 163 return -1; 164 ret = usb_bulk_msg(dev, 165 usb_rcvbulkpipe(dev, 5), 166 bulk_buf, 167 len, 168 &alen, 169 500); /* timeout in milliseconds */ 170 return ret; 171} 172 173/* -- send a value -- */ 174static int snd_val(struct gspca_dev *gspca_dev, 175 int ads, 176 unsigned int val) 177{ 178 struct usb_device *dev = gspca_dev->dev; 179 int alen, ret; 180 __u8 value, seq; 181 unsigned char bulk_buf[4]; 182 183 if (ads == 0x003f08) { 184 ret = reg_read(gspca_dev, 0x0704, &value); 185 if (ret < 0) 186 goto ko; 187 ret = reg_read(gspca_dev, 0x0705, &seq); 188 if (ret < 0) 189 goto ko; 190 ret = reg_read(gspca_dev, 0x0650, &value); 191 if (ret < 0) 192 goto ko; 193 reg_write(gspca_dev, 0x654, seq); 194 } else 195 reg_write(gspca_dev, 0x654, (ads >> 16) & 0xff); 196 reg_write(gspca_dev, 0x655, (ads >> 8) & 0xff); 197 reg_write(gspca_dev, 0x656, ads & 0xff); 198 reg_write(gspca_dev, 0x657, 0); 199 reg_write(gspca_dev, 0x658, 0x04); /* size */ 200 reg_write(gspca_dev, 0x659, 0); 201 reg_write(gspca_dev, 0x65a, 0); 202 reg_write(gspca_dev, 0x65b, 0); 203 reg_write(gspca_dev, 0x650, 5); 204 bulk_buf[0] = (val >> 24) & 0xff; 205 bulk_buf[1] = (val >> 16) & 0xff; 206 bulk_buf[2] = (val >> 8) & 0xff; 207 bulk_buf[3] = val & 0xff; 208 ret = usb_bulk_msg(dev, 209 usb_sndbulkpipe(dev, 6), 210 bulk_buf, 211 4, 212 &alen, 213 500); /* timeout in milliseconds */ 214 if (ret < 0) 215 goto ko; 216 if (ads == 0x003f08) { 217 seq += 4; 218 seq &= 0x3f; 219 reg_write(gspca_dev, 0x705, seq); 220 } 221 return ret; 222ko: 223 PDEBUG(D_ERR, "snd_val err %d", ret); 224 return ret; 225} 226 227/* set a camera parameter */ 228static int set_par(struct gspca_dev *gspca_dev, 229 int parval) 230{ 231 return snd_val(gspca_dev, 0x003f08, parval); 232} 233 234static void setbrightness(struct gspca_dev *gspca_dev) 235{ 236 struct sd *sd = (struct sd *) gspca_dev; 237 int parval; 238 239 PDEBUG(D_CONF, "brightness: %d", sd->brightness); 240 parval = 0x06000000 /* whiteness */ 241 + (sd->brightness << 16); 242 set_par(gspca_dev, parval); 243} 244 245static void setcontrast(struct gspca_dev *gspca_dev) 246{ 247 struct sd *sd = (struct sd *) gspca_dev; 248 int parval; 249 250 PDEBUG(D_CONF, "contrast: %d", sd->contrast); 251 parval = 0x07000000 /* contrast */ 252 + (sd->contrast << 16); 253 set_par(gspca_dev, parval); 254} 255 256static void setcolors(struct gspca_dev *gspca_dev) 257{ 258 struct sd *sd = (struct sd *) gspca_dev; 259 int parval; 260 261 PDEBUG(D_CONF, "saturation: %d", 262 sd->colors); 263 parval = 0x08000000 /* saturation */ 264 + (sd->colors << 16); 265 set_par(gspca_dev, parval); 266} 267 268/* this function is called at probe time */ 269static int sd_config(struct gspca_dev *gspca_dev, 270 const struct usb_device_id *id) 271{ 272 struct sd *sd = (struct sd *) gspca_dev; 273 struct cam *cam = &gspca_dev->cam; 274 275 cam->dev_name = (char *) id->driver_info; 276 cam->epaddr = 0x02; 277 gspca_dev->cam.cam_mode = vga_mode; 278 gspca_dev->cam.nmodes = sizeof vga_mode / sizeof vga_mode[0]; 279 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; 280 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; 281 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; 282 return 0; 283} 284 285/* this function is called at open time */ 286static int sd_open(struct gspca_dev *gspca_dev) 287{ 288 __u8 value; 289 int ret; 290 291 /* check if the device responds */ 292 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 293 ret = reg_read(gspca_dev, 0x0740, &value); 294 if (ret < 0) 295 return ret; 296 if (value != 0xff) { 297 PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", value); 298 return -1; 299 } 300 return 0; 301} 302 303/* -- start the camera -- */ 304static void sd_start(struct gspca_dev *gspca_dev) 305{ 306 __u8 dum; 307 int ret, value; 308 309 /* work on alternate 1 */ 310 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 311 312 set_par(gspca_dev, 0x10000000); 313 set_par(gspca_dev, 0x00000000); 314 set_par(gspca_dev, 0x8002e001); 315 set_par(gspca_dev, 0x14000000); 316 if (gspca_dev->width > 320) 317 value = 0x8002e001; /* 640x480 */ 318 else 319 value = 0x4001f000; /* 320x240 */ 320 set_par(gspca_dev, value); 321 ret = usb_set_interface(gspca_dev->dev, 322 gspca_dev->iface, 323 gspca_dev->alt); 324 if (ret < 0) 325 goto out; 326 ret = reg_read(gspca_dev, 0x0630, &dum); 327 if (ret < 0) 328 goto out; 329 rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */ 330 ret = reg_read(gspca_dev, 0x0650, &dum); 331 if (ret < 0) 332 goto out; 333 snd_val(gspca_dev, 0x000020, 0xffffffff); 334 reg_write(gspca_dev, 0x0620, 0); 335 reg_write(gspca_dev, 0x0630, 0); 336 reg_write(gspca_dev, 0x0640, 0); 337 reg_write(gspca_dev, 0x0650, 0); 338 reg_write(gspca_dev, 0x0660, 0); 339 setbrightness(gspca_dev); /* whiteness */ 340 setcontrast(gspca_dev); /* contrast */ 341 setcolors(gspca_dev); /* saturation */ 342 set_par(gspca_dev, 0x09800000); /* Red ? */ 343 set_par(gspca_dev, 0x0a800000); /* Green ? */ 344 set_par(gspca_dev, 0x0b800000); /* Blue ? */ 345 set_par(gspca_dev, 0x0d030000); /* Gamma ? */ 346 set_par(gspca_dev, lightfreq == 60 347 ? 0x33780000 /* 60 Hz */ 348 : 0x33640000); /* 50 Hz */ 349 350 /* start the video flow */ 351 set_par(gspca_dev, 0x01000000); 352 set_par(gspca_dev, 0x01000000); 353 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); 354 return; 355out: 356 PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); 357} 358 359static void sd_stopN(struct gspca_dev *gspca_dev) 360{ 361 struct usb_device *dev = gspca_dev->dev; 362 __u8 value; 363 364 set_par(gspca_dev, 0x02000000); 365 set_par(gspca_dev, 0x02000000); 366 usb_set_interface(dev, gspca_dev->iface, 1); 367 reg_read(gspca_dev, 0x0630, &value); 368 rcv_val(gspca_dev, 0x000020, 4); /* << (value ff ff ff ff) */ 369 reg_read(gspca_dev, 0x0650, &value); 370 snd_val(gspca_dev, 0x000020, 0xffffffff); 371 reg_write(gspca_dev, 0x0620, 0); 372 reg_write(gspca_dev, 0x0630, 0); 373 reg_write(gspca_dev, 0x0640, 0); 374 reg_write(gspca_dev, 0x0650, 0); 375 reg_write(gspca_dev, 0x0660, 0); 376 PDEBUG(D_STREAM, "camera stopped"); 377} 378 379static void sd_stop0(struct gspca_dev *gspca_dev) 380{ 381} 382 383static void sd_close(struct gspca_dev *gspca_dev) 384{ 385} 386 387static void sd_pkt_scan(struct gspca_dev *gspca_dev, 388 struct gspca_frame *frame, /* target */ 389 unsigned char *data, /* isoc packet */ 390 int len) /* iso packet length */ 391{ 392 int l; 393 static unsigned char ffd9[] = {0xff, 0xd9}; 394 395 /* a frame starts with: 396 * - 0xff 0xfe 397 * - 0x08 0x00 // length (little endian ?!) 398 * - 4 bytes = size of whole frame (big endian - including header) 399 * - 0x00 0x0c 400 * - 0xff 0xd8 401 * - .. JPEG image with escape sequences (ff 00) 402 */ 403 if (data[0] == 0xff && data[1] == 0xfe) { 404 if (gspca_dev->last_packet_type == INTER_PACKET) { 405 PDEBUG(D_ERR|D_FRAM, "sof actual l: %d init l: %d", 406 frame->data_end - frame->data, 407 frame->v4l2_buf.bytesused); 408 } 409 410 /* put the JPEG headaer */ 411 jpeg_put_header(gspca_dev, frame, sd_quant, 0x22); 412 413 /* beginning of the frame */ 414#define STKHDRSZ 12 415 l = (data[4] << 24) /* frame size */ 416 + (data[5] << 16) 417 + (data[6] << 8) 418 + data[7] 419 - STKHDRSZ 420 + (frame->data_end - frame->data) 421 + 2; /* EOF (ff d9) */ 422 gspca_frame_add(gspca_dev, INTER_PACKET, frame, 423 data + STKHDRSZ, len - STKHDRSZ); 424#undef STKHDRSZ 425 frame->v4l2_buf.bytesused = l; 426 return; 427 } 428 if (gspca_dev->last_packet_type != INTER_PACKET) { 429 if (gspca_dev->last_packet_type == LAST_PACKET) { 430 PDEBUG(D_ERR|D_PACK, "mof actual l: %d init l: %d", 431 frame->data_end - frame->data, 432 frame->v4l2_buf.bytesused); 433 } 434 return; 435 } 436 437 /* intermediate packet */ 438 l = frame->data_end - frame->data; 439 if (len < frame->v4l2_buf.bytesused - 2 - l) { 440 gspca_frame_add(gspca_dev, INTER_PACKET, frame, 441 data, len); 442 return; 443 } 444 445 /* last packet */ 446 if (len > frame->v4l2_buf.bytesused - 2 - l) 447 len = frame->v4l2_buf.bytesused - 2 - l; 448 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); 449 gspca_frame_add(gspca_dev, LAST_PACKET, frame, ffd9, 2); 450} 451 452static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 453{ 454 struct sd *sd = (struct sd *) gspca_dev; 455 456 sd->brightness = val; 457 if (gspca_dev->streaming) 458 setbrightness(gspca_dev); 459 return 0; 460} 461 462static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 463{ 464 struct sd *sd = (struct sd *) gspca_dev; 465 466 *val = sd->brightness; 467 return 0; 468} 469 470static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 471{ 472 struct sd *sd = (struct sd *) gspca_dev; 473 474 sd->contrast = val; 475 if (gspca_dev->streaming) 476 setcontrast(gspca_dev); 477 return 0; 478} 479 480static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 481{ 482 struct sd *sd = (struct sd *) gspca_dev; 483 484 *val = sd->contrast; 485 return 0; 486} 487 488static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 489{ 490 struct sd *sd = (struct sd *) gspca_dev; 491 492 sd->colors = val; 493 if (gspca_dev->streaming) 494 setcolors(gspca_dev); 495 return 0; 496} 497 498static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 499{ 500 struct sd *sd = (struct sd *) gspca_dev; 501 502 *val = sd->colors; 503 return 0; 504} 505 506/* sub-driver description */ 507static struct sd_desc sd_desc = { 508 .name = MODULE_NAME, 509 .ctrls = sd_ctrls, 510 .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0], 511 .config = sd_config, 512 .open = sd_open, 513 .start = sd_start, 514 .stopN = sd_stopN, 515 .stop0 = sd_stop0, 516 .close = sd_close, 517 .pkt_scan = sd_pkt_scan, 518}; 519 520/* -- module initialisation -- */ 521#define DVNM(name) .driver_info = (kernel_ulong_t) name 522static __devinitdata struct usb_device_id device_table[] = { 523 {USB_DEVICE(0x05e1, 0x0893), DVNM("Syntek DV4000")}, 524 {} 525}; 526MODULE_DEVICE_TABLE(usb, device_table); 527 528/* -- device connect -- */ 529static int sd_probe(struct usb_interface *intf, 530 const struct usb_device_id *id) 531{ 532 PDEBUG(D_PROBE, "camera probe"); 533 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd)); 534} 535 536static struct usb_driver sd_driver = { 537 .name = MODULE_NAME, 538 .id_table = device_table, 539 .probe = sd_probe, 540 .disconnect = gspca_disconnect, 541}; 542 543/* -- module insert / remove -- */ 544static int __init sd_mod_init(void) 545{ 546 if (usb_register(&sd_driver) < 0) 547 return -1; 548 info("v%s registered", version); 549 return 0; 550} 551static void __exit sd_mod_exit(void) 552{ 553 usb_deregister(&sd_driver); 554 info("deregistered"); 555} 556 557module_init(sd_mod_init); 558module_exit(sd_mod_exit); 559 560module_param(lightfreq, int, 0644); 561MODULE_PARM_DESC(lightfreq, "Light frequency 50 or 60 Hz"); 562module_param_named(quant, sd_quant, int, 0644); 563MODULE_PARM_DESC(quant, "Quantization index (0..8)"); 564